package com.tfjybj.itoo.exam.provider.service.impl;

import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.Reference;;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.dmsdbj.itoo.tool.business.ItooResult;
import com.dmsdbj.itoo.tool.tojson.JacksonJsonUntil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.internal.MongoClientImpl;
import com.mongodb.client.model.Filters;
import com.tfjybj.itoo.exam.entity.*;
import com.tfjybj.itoo.exam.ext.mongo.Option;
import com.tfjybj.itoo.exam.ext.mongo.Question;
import com.tfjybj.itoo.exam.model.*;
import com.tfjybj.itoo.exam.provider.dao.PaperRecordDao;
import com.tfjybj.itoo.exam.provider.service.*;
import com.tfjybj.itoo.exam.provider.until.ConstantUtils;
import com.tfjybj.itoo.exam.provider.until.DateTimeUtils;
import com.tfjybj.itoo.exam.provider.until.OnlineExamUtils;
import com.tfjybj.itoo.teach.FacadeApi.CourseApi;
import lombok.extern.slf4j.Slf4j;
import org.bson.BsonDocument;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.ArrayOperators;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Field;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.transaction.Transactional;
import java.io.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * OnlineExamService接口
 *
 * @author 任蒙蒙
 * @version 2.0.0
 * @since 2.0.0 2018-11-16 14:57:42
 */
@SuppressWarnings({"ALL", "unchecked"})
@Service("onlineExamService")
@Slf4j
public class OnlineExamServiceImpl implements OnlineExamService {

    /**
     * redis命名规范 服务简写+ 类名+自定义名
     */
    static final String REDIS_KEY_PRO_NAME = OnlineExamUtils.REDIS_SERVICE_NAME + OnlineExamUtils.REDIS_CONNECTOR + "OnlineExamServiceImpl" + OnlineExamUtils.REDIS_CONNECTOR;

    /**
     * 考生未登录
     */
    private static final int EXAM_STATUS_UNLOGIN = 0;

    /**
     * 抽题状态为1
     */
    private static final int QUESTION_STATUS_OVER = 1;
    /**
     * 考试状态为3表示已经交卷
     */
    private static final int EXAM_STATUS_OVER = 3;

    private static final String Selection = "0";
    private static final String Fixed = "1";
    private static final String Random = "2";

//    public enum organizingType {
//        Selection, Fixed, Random
//    };


    /**
     * 考试id查询试题
     */
    private static final String TEMPLATE_REDIS_INFO = "TEMPLATE_REDIS_INFO";
    /**
     * redis命名规范 服务简写+ 类名+自定义名
     */
    private static final String TEMPLATEDETAIL_REDIS_INFO = "TEMPLATEDETAIL_REDIS_INFO";
    @Resource
    private ExaminationService examinationService;
    @Resource
    private QuestionTypeService questionTypeService;
    @Resource
    private QuestionService questionService;
    @Resource
    private ExamRoomService examRoomService;
    @Resource
    private PaperRecordService paperRecordService;
    @Resource
    private RedisTemplate redisTemplate;
    @Resource
    private TemplateService templateService;
    @Resource
    private TemplateDetailsService templateDetailsService;
    @Resource
    private TeacherCourseService teacherCourseService;
    @Resource
    private ExamineeService examineeService;
    @Resource
    private ExamNotesService examNotesService;
    @Resource
    private PaperRecordDao paperRecordDao;
    @Resource
    private TemplateDetailsExtractService templateDetailsExtractService;
    @Resource
    private TemplateDetailsCustomService templateDetailsCustomService;
    @Resource
    private JudgeTaskService judgeTaskService;
    @Resource
    private CourseService courseService;

    @DubboReference(check = false)
    private CourseApi courseApi;

    @Resource
    private EvaluationMainService evaluationMainService;

    @Resource
    private EvaluationPaperService evaluationPaperService;

    @Resource
    private EvaluationPaperDetailService evaluationPaperDetailService;

    @Resource
    private ChangeQuestionService changeQuestionService;

//    @Autowired
//    private RedissonClient redissonClient;

    @Resource
    private StudentService studentService;

    @Autowired
    private MongoTemplate mongoTemplate;


    /**
     * 获取二次登陆密码
     */
    @Value("${secondLoginPassword}")
    private String secondLoginPassword;
    private List<QuestionMainModel> questionSubModelsList;

    /**
     * 查询系统中所有题型信息
     *
     * @return 所有题型信息
     * @author 王雪芬
     * @since 2.0.0 2018-11-16 17:10:28
     */
    @Override
    public List<QuestionTypeModel> selectQuestionTypeId() {
        List<QuestionTypeModel> questionTypeEntityList = questionTypeService.queryAllQuestionType();
        return questionTypeEntityList;
    }

    @Override
    public ExamNotesModel queryExamNotes(String examId) {
        return examNotesService.queryExamNotes(examId);
    }


    /**
     * 通过考试id查询试题存储到reids
     * 混合预加载和手动预加载都调用
     *
     * @param examId   考试id
     * @param operator 操作人
     * @author 王雪芬
     * @since 2.0.0 2018年11月21日16:01:32
     */
    @Override
    public boolean queryExamOnlineQuestionInfo(String examId, String operator) {

        try {
            String courseId = examinationService.queryExamOnlineQuestionInfo(examId, operator);

            if (StringUtils.isEmpty(courseId)) {
                log.error("courseId 为空" + getClass());
                return false;
            }
            //加operator 任蒙蒙
            if (StringUtils.isEmpty(operator)) {
                log.error("operator 为空" + getClass());
                return false;
            }
            //父题
            List<QuestionMainModel> questionMainModels = questionService.queryAllProblemByCourseId(courseId, operator);
            //子题
            List<QuestionMainModel> questionSubModelsList = questionService.selectQuestionByParentId(courseId, operator);

            // Map<QuestionMainModel.getId,QuestionMainModel>
            if (questionMainModels != null) {
                Map<String, QuestionMainModel> questionMainModelMap = new HashMap<>(questionMainModels.size() * 2);
                for (QuestionMainModel questionMainModel : questionMainModels) {
                    questionMainModelMap.put(questionMainModel.getQuestionId(), questionMainModel);
                }

                //混合题处理
                //根据父id与子id对应关系得到子题
                for (QuestionMainModel questionSubModel : questionSubModelsList) {
                    QuestionMainModel mainModel = questionMainModelMap.get(questionSubModel.getParentId());
                    if (mainModel != null) {
                        List<QuestionMainModel> questionMainSubList = mainModel.getQuestionMainModelList();
                        if (questionMainSubList == null) {
                            questionMainSubList = new ArrayList<>();
                        }
                        questionMainSubList.add(questionSubModel);
                        mainModel.setQuestionMainModelList(questionMainSubList);
                    }
                }
            }
            if (CollectionUtils.isEmpty(questionMainModels)) {
                log.info("该课程" + courseId + "下没有题,无法存储redis");
                return false;
            }
            String keyName = TEMPLATE_REDIS_INFO + "_" + courseId.trim() + "_" + operator.trim();
            redisTemplate.opsForValue().set(keyName, questionMainModels, 3600 * 4, TimeUnit.SECONDS);
            log.info("该课程" + courseId + "存储redis");
        } catch (Exception e) {
            log.error("queryExamOnlineQuestionInfo试题存储到reids" + e.getMessage());
            return false;
        }
        return true;
    }

    /**
     * 通过考试id和操作人查询考试信息
     *
     * @param examId   考试id
     * @param operator 操作人
     * @author 王雪芬
     * @since 2.0.0 2018年11月21日16:01:32     *
     */
    @Override
    public List<ExamOnlineinforedisModel> examOnlineInfo(String examId, String operator) {

        List<ExamOnlineinforedisModel> examOnlineInfoRedisModels = examinationService.examOnlineInfo(examId, operator);

        if (CollectionUtils.isEmpty(examOnlineInfoRedisModels)) {
            log.error(" 考试信息为空，方法名为：examOnlineInfo");
        }
        return examOnlineInfoRedisModels;
    }


    @Override
    public List<QuestionMainModel> examOnlineQuestionGetRedis(String examId, String operator) {

        //得到courseid
        String courseById = examinationService.queryOnlineCourseById(examId, operator);
        if (StringUtils.isEmpty(courseById)) {
            return null;
        }

        //从redis中查询信息
        String keyName = TEMPLATE_REDIS_INFO + courseById.trim() + operator.trim();

        List<QuestionMainModel> examOnlineQuestionList = null;
        try {
            examOnlineQuestionList = (List<QuestionMainModel>) redisTemplate.opsForValue().get(keyName);
        } catch (Exception e) {
            log.error("redis中key为" + keyName + "查询失败", e.getMessage());
            return null;
        }
        if (CollectionUtils.isEmpty(examOnlineQuestionList)) {
            List<QuestionMainModel> questionMainModels = questionService.queryAllProblemByCourseId(courseById, operator);
            redisTemplate.opsForValue().set(keyName, questionMainModels, 3600 * 4, TimeUnit.SECONDS);
        }
        return examOnlineQuestionList;
    }


    /**
     * 根据操作人id查询正在进行的考场
     *
     * @param operator 操作人 可有可无
     * @author 王雪芬
     * @since 2.0.0 2018年11月22日16:01:32
     */
    @Override
    public List<ExamRoomModel> examOnlineExamRoom(String operator) {
        return examRoomService.queryExamRoom(operator);
    }


    @Override
    public List<ExaminationModel> queryExamTimeInfo(String operator) {
        List<ExaminationModel> examinationModelList = examinationService.queryExamTimeInfo(operator);
        return examinationModelList;
    }

    /**
     * 1.学生登录接口
     *
     * @param studentId 传入学生学号
     * @return
     */
    @Override
    public ExaminOnlineModel queryExamStudentInfoLogin(String studentId) {
        //判断考试时间
        List<ExaminOnlineModel> examinOnlineModel = examineeService.queryExamExaminee(studentId);

        if (examinOnlineModel == null || examinOnlineModel.size() == 0) {
            log.warn("该学生没有考试,学生id为--{}", studentId);
            return null;
        }

        if (examinOnlineModel != null && examinOnlineModel.size() > 1) {
            log.warn("该学生有多场考试,学生id为--{}", studentId);
            examinOnlineModel.get(0).setStudentLoginCount(examinOnlineModel.size());
            return examinOnlineModel.get(0);
        }

        ExaminOnlineModel loginModel = examinOnlineModel.get(0);
        if (loginModel != null && loginModel.getStudentExamState() == 3) {
            log.warn("该学生已经交卷,学生id为--{}", studentId);
            return loginModel;
        }


        List<CourseEntity> byCourseId = courseService.getByCourseId(loginModel.getCourseId());
        if (byCourseId != null && byCourseId.size() > 0) {
            loginModel.setCourseName(byCourseId.get(0).getName());
        }
//        com.tfjybj.itoo.teach.entity.CourseEntity courseEntity = courseApi.findCourse(loginModel.getCourseId());
//        if (courseEntity != null) {
//            loginModel.setCourseName(courseEntity.getName());
//        }
        if (loginModel.getStudentExamState() == 0 ||
                (loginModel.getStudentExamState() == 1 && loginModel.getShouldSubmitTime() == null)) {
            //如果是初次登陆判断是否在考试时间范围之内
            ExaminationEntity examinationEntity = examinationService.loginExamStudentExaminOnline(loginModel.getExaminationIds());
            if (examinationEntity != null) {
                return loginModel;
            }
        } else if (loginModel.getShouldSubmitTime() != null && loginModel.getShouldSubmitTime().after(new Date())) {
            //如果考生为登陆过
            return loginModel;
        } else if (loginModel.getStudentExamState() == 3) {
            log.info("该学生已经交卷,考生id-{}", loginModel.getExameeid());
            return loginModel;
        }
        return null;
    }

    /**
     * 根据学号查询当前考试(或者距离最近的考试)中学生基本信息
     *
     * @param studentId 学号
     * @param exameeId  考生id  @return 学生信息
     * @author 王雪芬
     * @since 2018-11-23 15:51:29
     */
    @Override
    public ExamInfoModel queryExamStudentInfo(String examationId, String exameeId) {
        ExamInfoModel examInfoModel = new ExamInfoModel();
        //查询考试
        ExaminationEntity examinationEntity1 = examinationService.getById(examationId);
        if (examinationEntity1 == null) {
            return null;
        }
        examInfoModel.setExaminationEntity(examinationEntity1);

        //查询考生
        ExamineeEntity examineeEntity1 = examineeService.getById(exameeId);
        if (examineeEntity1 == null) {
            return null;
        }
        examInfoModel.setExamineeEntity(examineeEntity1);

        //根据模板id查询模板信息
        TemplateEntity templateEntity = templateService.getById(examinationEntity1.getTemplateId());
        if (templateEntity == null) {
            return null;
        }
        examInfoModel.setTemplateEntity(templateEntity);
        return examInfoModel;
    }


    @Override
    public boolean updateExamStateBySumit(ExamineeEntity examineeEntity) {
        //修改考生状态为已交卷
        examineeEntity.setStudentExamState(OnlineExamUtils.EXAM_STATE_SUBMIT_PAPER);
        //设置记录更新日期时间
        examineeEntity.setUpdateTime(DateTimeUtils.dateFormat(new Date()));
        boolean result = examineeService.updateById(examineeEntity);
        return result;
    }

    /**
     * 交卷修改状态,小练使用
     *
     * @return 考试
     * @author 闫伟强
     * @since 2.0.0 2019年7月12日17:41:47
     */
    @Override
    public boolean xiaoLianUpdateExamStateBySumit(ExamineeEntity examineeEntity) {
        //修改考生状态为已交卷
        examineeEntity.setStudentExamState(OnlineExamUtils.EXAM_STATE_NOT_SUBMIT);
        //设置记录更新日期时间
        examineeEntity.setUpdateTime(DateTimeUtils.dateFormat(new Date()));
        boolean result = examineeService.updateById(examineeEntity);
        return result;
    }


    @Override
    public long getExamRemainTime(String examineeId) {
        long remainDate = 0;
        ExamineeEntity examInfoModel = examineeService.getById(examineeId);
        if (examInfoModel != null && examInfoModel.getShouldSubmitTime() != null && !"".equals(examInfoModel.getShouldSubmitTime())) {
            //判断考生是否交卷
            if (examInfoModel.getStudentExamState().equals(3)) {
                return 0;
            }
            //用于监控->判断后台是否有问题,取的时候在监控使用REDI_MONITOR_STUDENTCODE/*
            redisTemplate.opsForValue().set("REDI_MONITOR_STUDENTCODE" + examInfoModel.getStudentCode(), true, 60, TimeUnit.SECONDS);
            //实际试卷时间理论交卷日期时间
            Date endDate = examInfoModel.getShouldSubmitTime();
            //long realEndTime = now();
            Date dayTime = new Date();
            long realEndTime = dayTime.getTime();
            //理论交卷时间与当前时间做比较
            remainDate = (endDate.getTime() - realEndTime);
            return remainDate;
        }
        return remainDate;
    }


    /**
     * 获取当前时间4个小时内所有的所有考试-考试预加载-王雪芬-2018年11月24日
     *
     * @return 考试
     * @author 王雪芬
     * @since 2.0.0 2018年11月22日21:22:58
     */
    @Override
    public int getExamResourse() {
        List<ExaminationModel> examinationModelList = examinationService.getExamResourse();
        if (CollectionUtils.isEmpty(examinationModelList)) {
            return 0;
        }
        try {
            for (ExaminationModel examinationModel : examinationModelList) {
                //加日志和修改operator --任蒙蒙
                String examinationId = examinationModel.getId();
                String operator = examinationModel.getOperator();
                if (examinationId == null || operator == null) {
                    log.error("该场考试的examinationId is null or operator is null,examinationModel-{}", examinationModel);
                    continue;
                }
                queryExamOnlineQuestionInfo(examinationId, operator);
            }
        } catch (Exception e) {
            return 0;
        }
        return 1;
    }

    /**
     * 二次登陆更新ip
     *
     * @param studentId 学生id
     * @param ip        更换机器后ip
     * @return 是否保存成功
     * @author 邓立瑶
     * @since 2.0.0 2018年11月24日14:52:06
     */
    @Override
    public boolean updateReLoginIP(String examineeId, String ip) {
        if (examineeId == null) {
            log.warn("二次登陆更新ip,学生id is null,ip-{}", ip);
            return false;
        }

        ExamineeEntity examineeEntity = new ExamineeEntity();
        //查询考生id
        QueryWrapper<ExamineeEntity> examineeQueryWrapper = new QueryWrapper<>(examineeEntity);
        examineeQueryWrapper.eq("id", examineeId);
        examineeQueryWrapper.eq("is_delete", 0);
        List<ExamineeEntity> examineeList = examineeService.list(examineeQueryWrapper);
        if (examineeEntity != null && examineeList.size() > 0) {
            String examineeIp = new String();
            //追加ip
            if (examineeList.get(0).getStudentIp() != null) {
                examineeIp = examineeList.get(0).getStudentIp() + "|" + ip;
            } else {
                examineeIp = ip;
            }

            //设置登陆IP
            examineeEntity.setStudentIp(examineeIp);
            QueryWrapper<ExamineeEntity> examineeEntityQueryWrapper = new QueryWrapper<>();
            examineeEntityQueryWrapper.eq("id", examineeId);
            examineeEntityQueryWrapper.eq("is_delete", 0);
            //更新 考生考试状态
            boolean result = examineeService.update(examineeEntity, examineeEntityQueryWrapper);
            return result;
        }
        return false;
    }

    /**
     * 从答题记录表中获取学生答案-2019年4月17日
     *
     * @param examPaperModel 试卷
     * @param eamineeId      考生id
     * @param templateId     模板id
     * @return ExamPaperModel
     * @Author 李娜
     */
    @Override
    public ExamPaperModel getExamPaperRecord(ExamPaperModel examPaperModel, String eamineeId, String templateId) {
        List<PaperRecordModel> paperRecordAnswerModels = paperRecordService.queryRecordStudentAnswer(eamineeId, templateId, examPaperModel.getCourseId());
        for (int i = 0; i < examPaperModel.getPaperQuestionTypeList().size(); i++) {
            List<QuestionMainModel> questionMainModelList = examPaperModel.getPaperQuestionTypeList().get(i).getQuestionMainModelList();
            if (CollectionUtils.isEmpty(questionMainModelList)) {
                log.warn("回显学生答案没有题干eamineeId-{},templateId-{},examPaperModel.getCourseId()-{},querstionTypeid-{}", eamineeId, templateId, examPaperModel.getCourseId());
                return null;
            }
            getPaperRecordAnswer(questionMainModelList, examPaperModel, paperRecordAnswerModels);
        }
        return examPaperModel;
    }

    /**
     * 递归试题获取答案
     *
     * @param questionMainModelList
     * @param examPaperModel
     * @param paperRecordAnswerModels
     * @return
     * @Author 李娜
     */
    public void getPaperRecordAnswer(List<QuestionMainModel> questionMainModelList, ExamPaperModel examPaperModel, List<PaperRecordModel> paperRecordAnswerModels) {
        Map<String, QuestionMainModel> questionMainModelMap = new HashMap<>();

        for (QuestionMainModel questionMainModel : questionMainModelList) {
            if (!ObjectUtils.isEmpty(questionMainModel)) {
                questionMainModelMap.put(questionMainModel.getQuestionId(), questionMainModel);
                for (PaperRecordModel paperRecordAnswerModel : paperRecordAnswerModels) {
                    if (!ObjectUtils.isEmpty(questionMainModelMap.get(paperRecordAnswerModel.getQuestionId())) && examPaperModel.getTemplateId().equals(paperRecordAnswerModel.getTemplateId()) && paperRecordAnswerModel.getStudentAnswer() != null) {
                        questionMainModelMap.get(paperRecordAnswerModel.getQuestionId()).setStudentAnswerArray(paperRecordAnswerModel.getStudentAnswer().split("\\|"));
                    }
                }
            }

            if (!CollectionUtils.isEmpty(questionMainModel.getQuestionMainModelList())) {
                getPaperRecordAnswer(questionMainModel.getQuestionMainModelList(), examPaperModel, paperRecordAnswerModels);
            }
        }
    }


    /**
     * 考生状态为0，进行抽题
     *
     * @param paperType
     * @param templateId
     * @param courseId
     * @param operator
     * @param examineeId
     * @param examinationId
     * @param examinationClassifyId
     * @return
     * @Author 李娜
     */
    public ItooResult findPaperByFirstLogin(ExamInfoModel examInfoModel, String clientIp, String sessionId) {

        ExamPaperModel examPaperModel = new ExamPaperModel();
        String paperType = examInfoModel.getTemplateEntity().getOrganizingType();
        String templateId = examInfoModel.getTemplateEntity().getId();
        String courseId = examInfoModel.getExaminationEntity().getCourseId();
        String operator = examInfoModel.getExaminationEntity().getOperator();
        String examineeId = examInfoModel.getExamineeEntity().getId();
        String examinationId = examInfoModel.getExaminationEntity().getId();
        String examinationClassifyId = examInfoModel.getExaminationEntity().getExamClassifyId();

        // 随机抽题 -李娜-2019年6月30日
        if (Random.equals(paperType.trim())) {
            examPaperModel = getPaperByTemplateRandom(templateId, examineeId, courseId, operator);
        }
        //选题,固定抽题
        if (Selection.equals(paperType.trim()) || Fixed.equals(paperType.trim())) {
            examPaperModel = getPaperByTemplateFix(templateId, examineeId, courseId, operator);
        }
        if (ObjectUtils.isEmpty(examPaperModel) || ObjectUtils.isEmpty(examPaperModel.getPaperQuestionTypeList())) {
            log.warn("抽卷失败,getPaperByTemplate查询为空,执行失败!templeatId-{},examineeId-{},courseId-{}", templateId, examineeId, courseId);
            return ItooResult.build("666666", "抽卷方法有问题,抽卷失败！");
        }

        examPaperModel.setExamclassifyId(examinationClassifyId);
        examPaperModel.setExaminationId(examinationId);

        // 业务题处理操作需要去掉答案
        examPaperModel = dealBusinessProblems(examPaperModel);
        if (examPaperModel == null) {
            log.warn("业务题处理失败,为空,templeatId-{},examineeId-{},courseId-{}", templateId, examineeId, courseId);
            return ItooResult.build(ItooResult.FAIL, "业务题试题处理异常");
        }
        // 对查询出的试卷进行排序-2019年6月30日
        getPaperSort(examPaperModel);

        // 将试卷插入答题记录
        //List<PaperRecordEntity> paperRecordEntityList = insertAllPaperRecord(examineeId, examinationId, examPaperModel);

//        if (CollectionUtils.isEmpty(paperRecordEntityList)) {
//            log.warn("更新答题记录失败，examineeId{},examinationId{}", examineeId, examinationId);
//            return ItooResult.build(ItooResult.FAIL, "更新答题记录失败");
//        }

        // 把考生试卷信息存入redis
        //String keyName = REDIS_KEY_PRO_NAME + ":" + examineeId + ":" + templateId + ":" + ConstantUtils.REDIS_PAPER_NAME;
        //redisTemplate.opsForValue().set(keyName, examPaperModel, 3600 * 2, TimeUnit.SECONDS);

        // 更新考生信息为已抽题
        Date endTime = null;
        if (examInfoModel.getExaminationEntity().getEndTime() != null) {
            endTime = examInfoModel.getExaminationEntity().getEndTime();
        }
        long duration = 0;
        if (examInfoModel.getExaminationEntity().getExamType() == null || examInfoModel.getExaminationEntity().getExamType() != 1) {
            duration = examInfoModel.getExaminationEntity().getExamDuration();
        }

        Boolean flag;
        Date startDate = new Date();
        if (endTime != null) {
            //更新考生状态已抽提和理论交卷时间--考评更新
            flag = updateStateExamStudent(endTime, duration, examineeId, clientIp);
        } else {
            //更新考生状态已抽提和理论交卷时间--随堂小练更新
            flag = updateStateExamStudent(examineeId, clientIp, startDate);
        }

        if (flag) {
            //存储key表示抽过题,二次登陆和刷新界面的时候使用
            //String sessionKeyName = REDIS_KEY_PRO_NAME + ":" + examineeId + ":" + clientIp + ":" + sessionId;
            //redisTemplate.opsForValue().set(sessionKeyName, examineeId, 3600 * 2, TimeUnit.SECONDS);
            examPaperModel.setExaminationId(examinationId);
            return ItooResult.build(ItooResult.SUCCESS, "抽提成功", examPaperModel);
        } else {
            log.warn("考生状态更新失败，examineeId{}", examineeId);
            return ItooResult.build(ItooResult.FAIL, "考生状态更新失败,抽题失败");
        }
    }

    /**
     * 考生刷新页面获取试卷
     * 已经登录抽过题,若redis 中有题，则可以直接从redis中获取试卷，然后再从数据库中获取答案
     * 若redis中没有试题，则直接从答题记录表中获取所有的试题回显试卷-李娜-2019年4月17日
     * 考试状态 0未登录，1已抽，2未交卷，3交卷
     *
     * @return
     * @Author lina
     */
    public ItooResult findPaperByRedis(ExamInfoModel examInfoModel, String clientIp, String sessionId) {
        String examineeId = examInfoModel.getExamineeEntity().getId();
        String templateId = examInfoModel.getTemplateEntity().getId();
        String paperType = examInfoModel.getTemplateEntity().getOrganizingType();
        String examinationId = examInfoModel.getExaminationEntity().getId();
        String examClassifyId = examInfoModel.getExaminationEntity().getExamClassifyId();

        ExamPaperModel examPaperModel = new ExamPaperModel();
        // 从redis取值
        String key = REDIS_KEY_PRO_NAME + ":" + examineeId + ":" + templateId + ":" + ConstantUtils.REDIS_PAPER_NAME;
        try {
            examPaperModel = (ExamPaperModel) redisTemplate.opsForValue().get(key);
        } catch (Exception e) {
            log.warn("从redis获取考生试卷失败，转从答题记录表获取试卷，examineeId{}", examineeId, e);
            examPaperModel = null;
        }
        if (!ObjectUtils.isEmpty(examPaperModel) && !CollectionUtils.isEmpty(examPaperModel.getPaperQuestionTypeList())) {
            // 获取学生答案
            examPaperModel = getExamPaperRecord(examPaperModel, examineeId, templateId);

            //业务题处理操作需要去掉答案
            examPaperModel = dealBusinessProblems(examPaperModel);
        }
        if (ObjectUtils.isEmpty(examPaperModel) || ObjectUtils.isEmpty(examPaperModel.getPaperQuestionTypeList())) {
            // 从答题记录表获取试卷
            examPaperModel = queryPaperAndRecord(examineeId, templateId);
            if (!ObjectUtils.isEmpty(examPaperModel)) {
                //业务题处理操作需要去掉答案
                examPaperModel = dealBusinessProblems(examPaperModel);
                //排序
                examPaperModel = getPaperSort(examPaperModel);
            } else {
                log.error("考生试卷显示，从redis以及答题记录表都获取失败，examineeId{}", examineeId);
                return null;
            }
        }

        examPaperModel.setExaminationId(examinationId);
        examPaperModel.setExamclassifyId(examClassifyId);

        // 看是否是二次登陆
        String keySecLogin = REDIS_KEY_PRO_NAME + ":" + examineeId + ":" + clientIp + ":" + sessionId;
        Object examineeIdInfo = redisTemplate.opsForValue().get(keySecLogin);
        if (ObjectUtils.isEmpty(examineeIdInfo)) {
            //第二次登陆更换ip
            updateReLoginIP(examineeId, clientIp);
            redisTemplate.opsForValue().set(keySecLogin, examineeId, 3600 * 2, TimeUnit.SECONDS);
            return ItooResult.build("0002", "二次登陆成功！", examPaperModel);
        } else {
            return ItooResult.build("0001", "刷新成功！", examPaperModel);
        }
    }

    public ItooResult judgeEmpty(ExamInfoModel examInfoModel, String clientIp) {
        String examineeId = examInfoModel.getExamineeEntity().getId();
        String examinationId = examInfoModel.getExaminationEntity().getId();

        if (ObjectUtils.isEmpty(examInfoModel)) {
            log.warn("获取考生信息为空 没有该学生,考生id-{},考试id-{},clientIp-{}", examineeId, examinationId, clientIp);
            return ItooResult.build(ItooResult.FAIL, "获取考生信息为空没有该学生,请联系后台管理人员");
        }

        if (ObjectUtils.isEmpty(examInfoModel.getExaminationEntity())) {
            log.warn("获取考试信息为空,考生id-{},考试-id{}", examineeId, examinationId);
            return ItooResult.build(ItooResult.FAIL, "获取考试信息为空,请联系后台管理人员");
        }
        if (ObjectUtils.isEmpty(examInfoModel.getExamineeEntity())) {
            log.warn("获取考生基本信息为空,考生id为-{},考试-id{}", examineeId, examinationId);
            return ItooResult.build(ItooResult.FAIL, "获取考生基本信息为空,请联系后台管理人员");
        }
        if (StringUtils.isEmpty(examInfoModel.getExamineeEntity().getStudentExamState())) {
            log.warn("考生状态不可以为空,考生id-{},考试id-{},clientIp-{}", examineeId, examinationId, clientIp);
            return ItooResult.build(ItooResult.FAIL, "考生状态有问题,请联系后台管理人员");
        }
        if (StringUtils.isEmpty(examInfoModel.getExaminationEntity().getTemplateId())) {
            log.warn("模板id不可以为空,考生id{},考试id-{}", examineeId, examinationId);
            return ItooResult.build(ItooResult.FAIL, "该考生模板有问题,请联系后台管理人员");
        }
        if (StringUtils.isEmpty(examInfoModel.getTemplateEntity().getOrganizingType())) {
            log.warn("组卷方式不可以为空,考生id{},考试id-{},clientIp-{},模板信息-{}", examineeId, examinationId, clientIp, examInfoModel.getTemplateEntity());
            return ItooResult.build(ItooResult.FAIL, "该考生模板组卷有问题,请联系后台管理人员");
        }
        if (StringUtils.isEmpty(examInfoModel.getExaminationEntity().getCourseId())) {
            log.warn("课程id不可以为空,考生id{}.考试信息-{}", examineeId, examInfoModel.getExaminationEntity());
            return ItooResult.build(ItooResult.FAIL, "该学生没有课程,请联系后台管理人员");
        }
        if (StringUtils.isEmpty(examInfoModel.getExaminationEntity().getId())) {
            log.warn("考试id不可以为空,考生信息", examInfoModel.getExamineeEntity());
            return ItooResult.build(ItooResult.FAIL, "该学生考试信息有问题,请联系后台管理人员");
        }
        if (StringUtils.isEmpty(examInfoModel.getExaminationEntity().getOperator())) {
            log.warn("该科考试的操作老师不可以为空,考生信息ExamineeEntity-{},考试信息ExaminationEntity-{}", examInfoModel.getExamineeEntity(), examInfoModel.getExaminationEntity());
            return ItooResult.build(ItooResult.FAIL, "操作人为空,考生id{}", examineeId);
        }
        return ItooResult.build(ItooResult.SUCCESS, "考生信息验证成功", examInfoModel);
    }

    /**
     * 更新考生状态为已抽题
     *
     * @param endTime
     * @param duration
     * @param examineeId
     * @return
     * @author 李娜
     */
    @Override
    public boolean updateStateExamStudent(Date endTime, long duration, String examineeId, String clientIp) {
        Date date = new Date();
        ExamineeEntity examineeEntity = new ExamineeEntity();

        long shouldTime = date.getTime() + duration * (60 * 1000);
        long examEndTime = endTime.getTime();
        Date shouldSubmitTime = new Date(Math.min(shouldTime, examEndTime));
        examineeEntity.setId(examineeId);
        examineeEntity.setStudentExamState(1);
        examineeEntity.setGetQuestionTime(date);
        examineeEntity.setStudentIp(clientIp);
        examineeEntity.setLoginTime(date);
        examineeEntity.setExamDuration(Math.toIntExact(duration));
        examineeEntity.setShouldSubmitTime(shouldSubmitTime);
        return examineeService.updateById(examineeEntity);
    }

    /**
     * 在线考试：根据学生ID生成本次考试试卷
     *
     * @param studentId  学生 ID
     * @param examineeId 考生 ID
     * @param clientIp
     * @return 试卷详情
     * @author 王雪芬, 李娜
     * @since 2.0.0 2018-11-27 17:10:28
     */
    @Override
    @Transactional(rollbackOn = Exception.class)
    public ItooResult findPaperByStudentIdForOnlineExam(String examinationId, String clientIp, String examineeId, String sessionId) {
        ExamPaperModel examPaperModel = new ExamPaperModel();
        //获取考生信息
        ExamInfoModel examInfoModel = queryExamStudentInfo(examinationId, examineeId);

        ItooResult itooResult = judgeEmpty(examInfoModel, clientIp);
        if (ItooResult.FAIL == itooResult.getCode()) {
            return itooResult;
        }

        int examState = examInfoModel.getExamineeEntity().getStudentExamState();

        /**
         * 考生本场考试状态为0(EXAM_STATUS_UNLOGIN)，未登录过，则按照模板规则进行抽题
         * 考生状态为1(QUESTION_STATUS_OVER)，已抽过卷，则从redis显示考生已经抽过的试卷
         * 考生状态为3(EXAM_STATUS_OVER)，证明学生已经交卷，直接提示用户已交卷
         */
        switch (examState) {
            case EXAM_STATUS_UNLOGIN:
                return findPaperByFirstLogin(examInfoModel, clientIp, sessionId);
            case QUESTION_STATUS_OVER:
                return findPaperByRedis(examInfoModel, clientIp, sessionId);
            case EXAM_STATUS_OVER:
                //已交卷
                return ItooResult.build("0003", "该学生已交卷！", examineeId);
            default:
                //状态错误
                log.warn("没有该学生的考试信息,考生id-{},考生状态-{}", examineeId, examState);
                return ItooResult.build(ItooResult.FAIL, "该学生状态错误！", examineeId + ";" + examState);
        }
    }


    /***
     *  王雪芬固定抽提和选题
     * @param templeatId 模板id
     * @param examineeId 考生id
     * @param courseId 课程id
     * @param operator 操作人
     * @return 试卷
     */
    public ExamPaperModel getPaperByTemplateFix(String templeatId, String examineeId, String courseId, String operator) {

        String templateExamineeCourseId = "practice_" + "templateId=" + templeatId + "_courseId=" + courseId + "operator=" + operator;

        ExamPaperModel examPaperModel = new ExamPaperModel();
        examPaperModel = (ExamPaperModel) redisTemplate.opsForValue().get(templateExamineeCourseId);
        //redis中没有数据
        if (examPaperModel == null) {
            ExamPaperModel paperByTemplateRandom = getPaperByTemplateRandom(templeatId, examineeId, courseId, operator);
            if (paperByTemplateRandom == null) {
                log.warn("固定抽提和随机抽提没有数据,templateId-{},examineeId-{},courseId-{},operator-{}", templeatId, examineeId, courseId, operator);
                return null;
            }
            redisTemplate.opsForValue().set(templateExamineeCourseId, paperByTemplateRandom);
            return paperByTemplateRandom;
        }
        return examPaperModel;
    }

    /**
     * 将题库的题加载到list（包括混合题的子题干）
     *
     * @param courseId 课程Id
     * @return QuestionMainModel 题干实体
     * @author 任蒙蒙 杨晓慧
     * @since 2.0.0 2018-12-12 14:10:28
     */
    public List<QuestionMainModel> getQuestionsByCourseId(String courseId, String operator) {
        long startTime = System.currentTimeMillis();
        //获取到所有的父题
        List<QuestionMainModel> questionMainModels = questionService.queryAllProblemByCourseId(courseId, operator);
        if (questionMainModels == null || questionMainModels.size() == 0) {
            log.error("模板随机抽题--加载题库--该课程下没有查询到试题或模板和考试配置的课程不同，课程courseId为:{},操作人operator为:{}", courseId, operator);
            return null;
        }

        //获取到所有的子题
        List<QuestionMainModel> questionSubModelsList = questionService.selectQuestionByParentId(courseId, operator);

        // Map<QuestionMainModel.getId,QuestionMainModel>
        // 下面两个for循环是为了匹配父子题关系，将父题放到map中，以questionId为key.
        Map<String, QuestionMainModel> questionMainModelMap = new HashMap<>(questionMainModels.size() * 2);
        for (QuestionMainModel questionMainModel : questionMainModels) {
            questionMainModelMap.put(questionMainModel.getQuestionId(), questionMainModel);
        }

        //混合题处理
        //根据父id与子id对应关系得到子题
        for (QuestionMainModel questionSubModel : questionSubModelsList) {
            // 根据子题的parentid从上面父题的map中找到对应的key，获取到对应的父题
            QuestionMainModel mainModel = questionMainModelMap.get(questionSubModel.getParentId());
            if (mainModel != null) {
                List<QuestionMainModel> questionMainSubList = mainModel.getQuestionMainModelList();
                if (questionMainSubList == null) {
                    questionMainSubList = new ArrayList<>();
                }
                questionMainSubList.add(questionSubModel);
                mainModel.setQuestionMainModelList(questionMainSubList);
            }
        }
        System.out.println("从数据库抽题的时间：" + (System.currentTimeMillis() - startTime) / 1000);
        // 返回父子题对应好的questionMainModels
        return questionMainModels;
    }

    @Autowired
    private com.tfjybj.itoo.exam.ext.service.QuestionService mongoQuestionService;

    @Autowired
    private com.tfjybj.itoo.exam.ext.service.TemplateService mongoTemplateService;

    /**
     * 抽卷
     */
    @Override
    public ExamPaperModel getPaperByTemplateRandom(String templateId, String examineeId, String courseId, String operator) {
        //用于记录日志--开始抽题
        String templateExamineeCourseId = "practice_" + "templateId=" + templateId + "_courseId=" + courseId + "operator=" + operator;
        log.info("开始抽题:" + templateExamineeCourseId);

        //用于控制的变量，0-自然随机；1-选中的章节均匀随机；（自然随机暂时没有用到）
        int randomType = 1;

        //试卷实体，用于存放抽取好的试卷
        ExamPaperModel examPaperModel = new ExamPaperModel();
        //用于保存题型list
        List<ExamTemPaperQuestionTypeModel> paperQuestionTypeList = new ArrayList<>();

        //region 1.将试题构造mainMap,以courseId +questionTypeId+chapter+degreeInitial为key
        //构造chapter，key为章节信息,value为本章节题目个数.并且按照题目数量从小到大排序.
        //加一个redis--examQuestionMainModelList存放从题库查到的该科目题库
        //List<QuestionMainModel> examQuestionMainModelList = getQuestionMainModelFromRedis(courseId, operator);
        List<QuestionMainModel> examQuestionMainModelList = mongoQuestionService.getQuestionMainModelFromMongo(courseId, operator);
        if (examQuestionMainModelList == null || examQuestionMainModelList.size() == 0) {
            log.error("模板随机抽题--该课程下没有查询到试题，课程id为:{}", courseId);
            return null;
        }
        long startTime = System.currentTimeMillis();

        // 获得所有题,以courseId +questionTypeId+chapter+degreeInitial为key(将该课程的题库按照题型，章节，难度等级分好类)
        Map<String, List<QuestionMainModel>> mainMap = new HashMap<>(examQuestionMainModelList.size() * 2);
        //HashMap<题型id,LinkedHashMap<章节id，某题型的章节数量>>
        HashMap<String, LinkedHashMap<String, Integer>> questionTypeChapterMap = new HashMap<>(examQuestionMainModelList.size() * 2);

        // 循环从数据库或者Redis查询的所有题，按题型，章节，难度等级放到对应的key下
        for (QuestionMainModel examQuestionMainModel : examQuestionMainModelList) {
            //加判空处理 --任蒙蒙
            if (examQuestionMainModel == null) {
                log.error("从题库取的该科的题examQuestionMainModel is null,课程id为courseId-{},operator-{},examineeId-{}", courseId, operator, examineeId);
                continue;
            }
            if (examQuestionMainModel != null) {
                // 获取到该题的题型，章节，难度等级信息
                String questionTypeId = examQuestionMainModel.getQuestionTypeId();
                String chapter = examQuestionMainModel.getQuestionClassifyId();
                Integer degree = examQuestionMainModel.getDegreeInitial();

                if (questionTypeId == null || chapter == null) {
                    log.warn("questionTypeId is null or chapter is null,题的id为examQuestionMainModel.getQuestionId()-{}", examQuestionMainModel.getQuestionId());
                    continue;
                }

                /*
                1.1 获得所有题，形成以courseId +questionTypeId+chapter+degreeInitial为key的map
                    courseId：课程id
                    questionTypeId：试卷类型id  单选题多选题
                    chapter：章节
                    degreeInitial：难度
                 */
                String key = courseId + "_" + questionTypeId + "_" + chapter + "_" + degree;
                List<QuestionMainModel> examQuestionMainModels = mainMap.get(key);
                if (examQuestionMainModels == null) {
                    examQuestionMainModels = new ArrayList<>();
                }
                examQuestionMainModels.add(examQuestionMainModel);
                //存到redis中,用courseId做key,因为所有的学生对应的这个课都是拿这些题
                mainMap.put(key, examQuestionMainModels);

                /*
                1.2 key为章节信息,value为本章节题目个数.
                 */
                LinkedHashMap<String, Integer> tmpChapterMap = questionTypeChapterMap.get(questionTypeId);
                // 每章节的第一个题进来时还没有定义map，所以需要先判空，再new一个新的，后面的其他题直接用这个map即可
                tmpChapterMap = (tmpChapterMap == null ? new LinkedHashMap<>() : tmpChapterMap);
                Integer integer = tmpChapterMap.get(chapter);
                integer = (integer == null ? 0 : integer);
                // 以章节id为key，各章节对应的题目数量随着循环次数递增
                tmpChapterMap.put(chapter, integer + 1);
                questionTypeChapterMap.put(questionTypeId, tmpChapterMap);
            }
        }
        /*
        1.3 将HashMap按照value的数量从小到大进行排序,输出为LinkedHashMap（LinkedHashMap内部维持了一个双向链表,可以保持顺序）
         */
        for (Map.Entry<String, LinkedHashMap<String, Integer>> mapEntry : questionTypeChapterMap.entrySet()) {
            questionTypeChapterMap.put(mapEntry.getKey(), sortMap(mapEntry.getValue()));
        }
        log.info("build question map time:{}", System.currentTimeMillis() - startTime);
//endregion

        //region 2.从模板模块获得模板和模板明细的信息
        TemplateQuestionTypeDetailModel templateDetailInfo = mongoTemplateService.getTemplateById(templateId);
        if (Objects.isNull(templateDetailInfo)) {
            log.error("get template from mongo is null");
            return null;
        }
        //endregion

        //region 3.根据模板明细的信息循环每个题型抽题 --任蒙蒙
        //题型List(模板明细)
        List<TemplateDetailsModel> templateDetailsModelList = templateDetailInfo.getTemplateDetailsModelList();

        for (TemplateDetailsModel templateQuestionTypeModel : templateDetailsModelList) {
            //用于保存抽取好的试题集合
            List<QuestionMainModel> alreadyQuestionMainList = new ArrayList<>();
            //抽题个数
            Integer questionCount = templateQuestionTypeModel.getQuestionNumber();
            //题型id
            String templateQuestionTypeId = templateQuestionTypeModel.getQuestionTypeId();
            //防止数据库中数据带有空格在代码中造成数据不一致，需要去除空格
            templateQuestionTypeId = templateQuestionTypeId.replaceAll("\r|\n\t", "");

            //设置该题型下每个小题的得分
            Double smallQuestionScore = null;
            try {
                // 获取模板设置的小题分值
                smallQuestionScore = Double.parseDouble(templateQuestionTypeModel.getSmallQuestionScore());
            } catch (NumberFormatException e) {
                log.error(e.getMessage(), e);
                log.error("模板随机抽题--模板明细的小题分值smallQuestionScore转为double类型失败" + templateQuestionTypeModel, e);
            }
            //模板设置分值有问题--方便看错误日志
            if (smallQuestionScore == null) {
                log.warn("smallQuestionScore is null,examQuestionMainModel-{}", templateQuestionTypeModel);
                continue;
            }
            if (smallQuestionScore < 0) {
                log.warn("smallQuestionScore(小题分值为负数),examQuestionMainModel-{}", templateQuestionTypeModel);
                continue;
            }
            // 获取到该题型下模板明细id
            String templatedetailsId = templateQuestionTypeModel.getId();

            //方便看错误日志
            if (questionCount == null || templateQuestionTypeId == null || templatedetailsId == null) {
                log.warn("模板随机抽题--该考试模板信息不足，模板id为:{}", templateId);
                continue;
            }

            //region 3.1 判断填空题是按空抽题还是按题抽题，blankflagflag为true时为按题抽题，为false时为按空抽题
            boolean blankflag;
            Integer isBlank = templateQuestionTypeModel.getIsBlanks();
            if (isBlank == null) {
                log.warn("smallQuestionScore is null,examQuestionMainModel-{}", templateQuestionTypeModel);
                continue;
            }
            if (isBlank == 1) {
                blankflag = false;
            } else {
                blankflag = true;
            }
            //endregion

            //region 3.2 有必抽题，先抽必抽题
            if (templateQuestionTypeModel.getIsExtract() == 1) {
                //根据模板明细id获得必抽题list 从内存中查询 使用下面的方式代替
                //List<QuestionMainModel> mustQuestionList = templateDetailsExtractService.queryQueExtractByTemplateId(templatedetailsId);

                Map<String, QuestionMainModel> questionId2Map = examQuestionMainModelList.stream()
                        .collect(Collectors.toMap(e -> e.getId(), e -> e));
                List<TemplateDetailsExtractModel> templateDetailsExtractModel = templateQuestionTypeModel.getTemplateDetailsExtractModel();
                //拿到必抽题的所有题id
                List<String> mustQuestionIds = templateDetailsExtractModel.stream()
                        .map(TemplateDetailsExtractModel::getQuestionId)
                        .collect(Collectors.toList());

                List<QuestionMainModel> mustQuestionList = new ArrayList<>();
                for (String questionId : mustQuestionIds) {
                    QuestionMainModel model = questionId2Map.get(questionId);
                    mustQuestionList.add(model);
                }


                //判断模板明细必抽题是否为空
                if (CollectionUtils.isEmpty(mustQuestionList)) {
                    log.warn("模板随机抽题--该考试模板明细必抽题信息不足，模板明细" +
                            "id为:{}", templatedetailsId);
                    continue;
                }
                Map<String, List<QuestionMainModel>> subQuesiton2Map = examQuestionMainModelList.stream()
                        .filter(e -> Objects.nonNull(e.getParentId()))
                        .collect(Collectors.groupingBy(QuestionMainModel::getParentId));
                //将混合题的父题和子题对应
                for (QuestionMainModel questionMainModels : mustQuestionList) {
                    if (questionMainModels == null) {
                        log.warn("questionMainModels is null,设必抽题的模板明细id为templatedetailsId-{}", templatedetailsId);
                        continue;
                    } else if (questionMainModels != null) {
                        String parentId = questionMainModels.getQuestionId();

                        //获得混合题或计算选择题的对应的子题,使用内存
                        //List<QuestionMainModel> questionSubModelsList = questionService.selectSubQuestionByParentId(parentId);
                        List<QuestionMainModel> questionSubModelsList = subQuesiton2Map.get(parentId);
                        if (this.questionSubModelsList == null) {
                            log.warn("模板随机抽题--该考试没有配混合题或该考试配的混合题没有子题，父题id为:{}", parentId);
                            continue;
                        }
                        //把查到的子题赋给父题
                        if (this.questionSubModelsList != null && this.questionSubModelsList.size() > 0) {
                            questionMainModels.setQuestionMainModelList(this.questionSubModelsList);
                        }
                    }
                }
                // 循环必抽题列表，将其加入已抽题集和
                for (QuestionMainModel mustQuestionModel : mustQuestionList) {
                    if (mustQuestionModel == null) {
                        log.warn("mustQuestionModel is null,设必抽题的模板明细id为templatedetailsId-{}", templatedetailsId);
                        continue;
                    }
                    if (mustQuestionModel != null) {
                        if (blankflag == true) {
                            // 按题目数量给分
                            mustQuestionModel.setScore(smallQuestionScore);
                        } else {
                            //给填空题每个小题赋分，按空给分
                            mustQuestionModel.setScore(mustQuestionModel.getOptionCount() * smallQuestionScore);
                        }
                        //将必抽题加入已抽题list
                        alreadyQuestionMainList.add(mustQuestionModel);
                        // questionCount表示剩余要抽题的数量，这里需要减去已抽题的数量
                        if (blankflag) {
                            //按题目数量
                            questionCount--;
                        } else {
                            //减去空数
                            questionCount -= mustQuestionModel.getOptionCount();
                        }
                    }
                }

            }
            //endregion

            List<QuestionMainModel> examQuestionMainModels;
            LinkedHashMap<String, Integer> subChapterMap = new LinkedHashMap<>();//存储已抽取的章节，用于补偿抽题中
            LinkedHashMap<String, Integer> chapterMap = new LinkedHashMap<>();//存储某题型下章节数及对应的题数
            List<Integer> degrees = new ArrayList<Integer>();

            //region 3.3 无定义设置，有自定义设置和补偿抽题的情况
            if (templateQuestionTypeModel.getIsCustom() == 0) {
                //region 3.3.1 无自定义设置 --isCustom=0
                //获得题库中对应题型下的章节个数
                chapterMap = questionTypeChapterMap.get(templateQuestionTypeId);
                //方便看错误日志
                if (chapterMap == null) {
                    log.warn("模板随机抽题--该考试模板明细题型和题库题型不对应或题库没有模板配置的该题型的题，模板明细题型id为:{}", templateQuestionTypeId);
                    continue;
                }
                //模板中设置的难度等级信息
                Integer degree = templateQuestionTypeModel.getDegree();
                //模板中设置的章节信息
                String chapter = templateQuestionTypeModel.getQuestionClassifyId();

                if (chapter == null || degree == null) {
                    log.warn("模板随机抽题--该考试模板明细试题分类或难度等级信息不足，模板明细题型id为:{}", templateQuestionTypeId);
                    continue;
                }
                List<String> chapters;  //

                // 前端默认设置随机章节
                if ("随机".equals(chapter)) {
                    // 设置随机时，默认从包含该题型的所有章节中抽题，
                    // 这里用keySet()方法可以把map中所有的key对应的是value都拿到,也就获取到了所有该题型下所有章节的信息 -- 杨晓慧
                    chapters = new ArrayList<String>(chapterMap.keySet());
                } else {
                    // 可以设置多个章节，前端传过来时候用"|"隔开，这里需要切割
                    chapters = Arrays.asList(chapter.split("\\|"));
                }
                //难度等级
                degrees = new ArrayList<Integer>();
                if (degree == 0) {
                    // 难度等级为0时候表示未设定难度等级，将会从0.1.2.3四个难度等级中抽题
                    degrees = Arrays.asList(new Integer[]{1, 2, 3, 0});
                } else {
                    // 已设置难度等级，遵循用户设置
                    degrees.add(degree);
                }

                examQuestionMainModels = new ArrayList<>();
                if (randomType == 0) {
                    //在所有章节中-自然随机抽题(自然随机抽题暂且用不到，这块代码待修改-任蒙蒙-2018年12月1日15:29:43)
                    examQuestionMainModels = takeQuestion(courseId, templateQuestionTypeId, chapters, degrees, mainMap, questionCount, alreadyQuestionMainList);

                } else if (randomType == 1) {
                    //章节均匀抽题
                    if ("随机".equals(chapter)) {
                        subChapterMap = chapterMap;
                    } else {
                        subChapterMap = new LinkedHashMap<>();
                        for (Map.Entry<String, Integer> entry : chapterMap.entrySet()) {
                            if (chapters.contains(entry.getKey())) {
                                subChapterMap.put(entry.getKey(), entry.getValue());
                            }
                        }
                    }
                    // 按照规则随机抽题，返回该题型抽到的题
                    examQuestionMainModels = takeChapterQuestion(courseId, templateQuestionTypeId, subChapterMap, degrees, mainMap, questionCount, blankflag, alreadyQuestionMainList);
                }
                //给抽到的每道题设置分值
                for (int i = 0; i < examQuestionMainModels.size(); i++) {
                    //若题为null值，加日志
                    if (examQuestionMainModels.get(i) == null) {
                        log.warn("设置得分时examQuestionMainModels.get(i) is null,examineeId-{},courseId-{}, templateId-{}, operator-{}", examineeId, courseId, templateId, operator);
                        continue;
                    }
                    //加判空处理
                    if (examQuestionMainModels.get(i) != null && !"[]".equals(examQuestionMainModels.get(i))) {
                        if (blankflag == true) {
                            examQuestionMainModels.get(i).setScore(smallQuestionScore);
                        } else {
                            //给填空题每个小题赋分
                            examQuestionMainModels.get(i).setScore(examQuestionMainModels.get(i).getOptionCount() * smallQuestionScore);
                        }
                    }
                }

                alreadyQuestionMainList.addAll(examQuestionMainModels);
                if (blankflag) {
                    questionCount = questionCount - examQuestionMainModels.size();
                } else {
                    for (int i = 0; i < examQuestionMainModels.size(); i++) {
                        //加日志
                        if (examQuestionMainModels.get(i) == null) {
                            log.warn("设置得分时examQuestionMainModels.get(i) is null,examineeId-{},courseId-{}, templateId-{}, operator-{}", examineeId, courseId, templateId, operator);
                            continue;
                        }
                        //加判空处理
                        if (examQuestionMainModels.get(i) != null && !"[]".equals(examQuestionMainModels.get(i))) {
                            // 减去已抽题的数量，questionCount存着该题型下待抽题的数量
                            questionCount -= examQuestionMainModels.get(i).getOptionCount();
                        }
                    }
                }
                // 待抽题的数量>0 ,题没有抽够，需要走补偿机制，从选中章节的其他难度等级抽题，不够时再从其他章节的其他难度等级抽题
                if (questionCount > 0) {
                    log.warn("题库内题目数量不足,题型Id=" + templateQuestionTypeId +
                            " 已抽出题目数量=" + examQuestionMainModels.size() + " 所需抽题数量=" + questionCount + templateExamineeCourseId);
                }
                //endregion

                //region 3.3.2 无定义时补偿抽题 todo 填空题按空给分时补偿机制待完善
                if (questionCount > 0) {
                    // 从已选章节的其他难度等级中抽题
                    List<Integer> allDegrees = new ArrayList<>();
                    // 添加所有的难度等级
                    allDegrees.addAll(Arrays.asList(new Integer[]{1, 2, 3, 0}));
                    if (questionCount > 0) {
                        // 将已经抽过的难度等级去掉，只留下之前没有抽过的难度等级，避免抽重题 --杨晓慧
                        allDegrees.removeAll(degrees);
                        // 走章节随机抽题的方法，返回抽到的题
                        examQuestionMainModels = takeChapterQuestion(courseId, templateQuestionTypeId, subChapterMap, allDegrees, mainMap, questionCount, blankflag, alreadyQuestionMainList);

                        //给抽到的题设置得分
                        for (int i = 0; i < examQuestionMainModels.size(); i++) {
                            //加日志
                            if (examQuestionMainModels.get(i) == null) {
                                log.warn("设置得分时examQuestionMainModels.get(i) is null,examineeId-{},courseId-{}, templateId-{}, operator-{}", examineeId, courseId, templateId, operator);
                                continue;
                            }
                            //加判空处理
                            if (examQuestionMainModels.get(i) != null && !"[]".equals(examQuestionMainModels.get(i))) {
                                if (blankflag == true) {
                                    // 按题给分--直接用模板给的小题分值
                                    examQuestionMainModels.get(i).setScore(smallQuestionScore);
                                } else {
                                    //按空数--给填空题每个小题赋分（小题分值=空数*每空分值）
                                    examQuestionMainModels.get(i).setScore(examQuestionMainModels.get(i).getOptionCount() * smallQuestionScore);
                                }
                            }
                        }

                        //将抽出的题加入已抽题集合.
                        alreadyQuestionMainList.addAll(examQuestionMainModels);
                        if (blankflag) {
                            // 减去已抽题的数量
                            questionCount = questionCount - examQuestionMainModels.size();
                        } else {
                            for (int i = 0; i < examQuestionMainModels.size(); i++) {
                                //加日志
                                if (examQuestionMainModels.get(i) == null) {
                                    log.warn("设置得分时examQuestionMainModels.get(i) is null,examineeId-{},courseId-{}, templateId-{}, operator-{}", examineeId, courseId, templateId, operator);
                                    continue;
                                }
                                //加判空处理
                                if (examQuestionMainModels.get(i) != null && !"[]".equals(examQuestionMainModels.get(i))) {
                                    // 减去已抽题数量
                                    questionCount -= examQuestionMainModels.get(i).getOptionCount();
                                }
                            }
                        }

                    }
                    if (questionCount > 0) {
                        //从剩余的章节范围重新抽题(如果原来已经是"随机",allChapters.removeAll(chapters)后allChapters将变为空,不影响程序执行)
                        LinkedHashMap<String, Integer> remainChapterMap = new LinkedHashMap<>();
                        //去除已抽到的章节
                        for (Map.Entry<String, Integer> entry : chapterMap.entrySet()) {
                            if (!subChapterMap.containsKey(entry.getKey())) {
                                remainChapterMap.put(entry.getKey(), entry.getValue());
                            }
                        }

                        List<Integer> degreeschapter = new ArrayList<>();
                        degreeschapter.addAll(Arrays.asList(new Integer[]{1, 2, 3, 0}));
                        // 从所有难度等级中抽题
                        examQuestionMainModels = takeChapterQuestion(courseId, templateQuestionTypeId, remainChapterMap, degreeschapter, mainMap, questionCount, blankflag, alreadyQuestionMainList);

                        //设置得分
                        for (int i = 0; i < examQuestionMainModels.size(); i++) {
                            //加日志
                            if (examQuestionMainModels.get(i) == null) {
                                log.warn("设置得分时examQuestionMainModels.get(i) is null,examineeId-{},courseId-{}, templateId-{}, operator-{}", examineeId, courseId, templateId, operator);
                                continue;
                            }
                            //加判空处理
                            if (examQuestionMainModels.get(i) != null && !"[]".equals(examQuestionMainModels.get(i))) {
                                if (blankflag == true) {
                                    examQuestionMainModels.get(i).setScore(smallQuestionScore);
                                } else {
                                    //按空给填空题每个小题赋分
                                    examQuestionMainModels.get(i).setScore(examQuestionMainModels.get(i).getOptionCount() * smallQuestionScore);
                                }
                            }
                        }

                        //将抽出的题加入集合.
                        alreadyQuestionMainList.addAll(examQuestionMainModels);
                        if (blankflag) {
                            questionCount = questionCount - examQuestionMainModels.size();
                        } else {
                            for (int i = 0; i < examQuestionMainModels.size(); i++) {
                                //加日志
                                if (examQuestionMainModels.get(i) == null) {
                                    log.warn("设置得分时examQuestionMainModels.get(i) is null,examineeId-{},courseId-{}, templateId-{}, operator-{}", examineeId, courseId, templateId, operator);
                                    continue;
                                }
                                //加判空处理
                                if (examQuestionMainModels.get(i) != null && !"[]".equals(examQuestionMainModels.get(i))) {
                                    questionCount -= examQuestionMainModels.get(i).getOptionCount();
                                }
                            }
                        }
                    }
                }
                //endregion
                // 补偿抽题数量不够，题库内数量不足
                if (questionCount > 0) {
                    log.error("扩大范围重抽题失败! 题库内题目数量不足,请检查配置,将进行补偿抽题,题型Id=" + templateQuestionTypeId +
                            " 抽出题目数量=" + examQuestionMainModels.size() + " 所需抽题数量=" + questionCount + templateExamineeCourseId);
                }

            } else {

                //region 3.3.3 有自定义设置和补偿抽题

                //记录补偿个数,最终统一补偿.
                int repairTotalCount = 0;

                // 去模板明细高级表查相关信息--任蒙蒙--2018年12月7日08:30:57  改为从内存查询
                List<TemplateDetailsCustomModel> templateDetailsCustomModel = templateQuestionTypeModel.getTemplateDetailsCustomModel();
                //List<TemplateDetailsModel> detailsCustomEntities = templateDetailsCustomService.queryTemDeCustomByTemDetailsId(templatedetailsId);
                if (templateDetailsCustomModel == null) {
                    log.warn("模板随机抽题--该考试模板明细自定义信息不足，模板明细id为:{}", templatedetailsId);
                    continue;
                }

                //region 根据模板明细高级表是否配置高级(isSenior)抽题和补偿抽题
                if (!CollectionUtils.isEmpty(templateDetailsCustomModel)) {

                    Integer isSenior = templateDetailsCustomModel.get(0).getIsSenior();
                    //方便看错误日志 --任蒙蒙 2018年12月14日10:25:55
                    if (isSenior == null) {
                        log.warn("模板随机抽题--该考试模板明细高级表，模板明细题型id为:{}", templateQuestionTypeId);
                        continue;
                    }
                    for (TemplateDetailsCustomModel detailEntity : templateDetailsCustomModel) {

                        //region 根据模板明细高级表是否配置高级(isSenior)抽题 --任蒙蒙
                        //有高级时
                        if (isSenior == 1 && isSenior != null) {
                            //有高级时，每小题的分从高级表中查
                            smallQuestionScore = Double.parseDouble(detailEntity.getQuestionScore());
                        }
                        //题型
                        chapterMap = questionTypeChapterMap.get(templateQuestionTypeId);
                        //方便看错误日志
                        if (chapterMap == null) {
                            log.warn("模板随机抽题--该考试模板明细高级表题型和题库题型不对应或题库没有模板配置的该题型的题，模板明细题型id为:{}", templateQuestionTypeId);
                            continue;
                        }
                        //章节
                        String chapter = detailEntity.getQuestionClassifyId();
                        //难度等级
                        Integer degree = detailEntity.getDegree();
                        //模板高级表每个难度等级个数
                        Integer questionNumber = detailEntity.getQuestionNumber();

                        //方便看错误日志
                        if (chapter == null || degree == null || questionNumber == null) {
                            log.warn("模板随机抽题--该考试模板明细高级表试题分类或难度等级或题的个数信息不足，模板明细题型id为:{}", templateQuestionTypeId);
                            continue;
                        }
                        questionCount = questionNumber;

                        List<String> chapters;
                        if ("随机".equals(chapter)) {
                            chapters = new ArrayList<String>(chapterMap.keySet());
                        } else {
                            chapters = Arrays.asList(chapter.split("\\|"));
                        }
                        //难度等级
                        degrees = new ArrayList<Integer>();
                        if (degree == 0) {
                            degrees = Arrays.asList(new Integer[]{1, 2, 3, 0});
                        } else {
                            degrees.add(degree);
                        }

                        examQuestionMainModels = new ArrayList<>();
                        if (randomType == 0) {
                            //自然随机抽题
                            examQuestionMainModels = takeQuestion(courseId, templateQuestionTypeId, chapters, degrees, mainMap, questionCount, alreadyQuestionMainList);
                            //这个效率高点
                            for (int i = 0; i < examQuestionMainModels.size(); i++) {
                                //加日志 --任蒙蒙
                                if (examQuestionMainModels.get(i) == null) {
                                    log.warn("设置得分时examQuestionMainModels.get(i) is null,examineeId-{},courseId-{}, templateId-{}, operator-{}", examineeId, courseId, templateId, operator);
                                    continue;
                                }
                                //加判空处理 --任蒙蒙 --2018年12月21日22:43:06
                                if (examQuestionMainModels.get(i) != null && !"[]".equals(examQuestionMainModels.get(i))) {
                                    examQuestionMainModels.get(i).setScore(smallQuestionScore);
                                }
                            }
                            //将抽出的题加入集合.
                            alreadyQuestionMainList.addAll(examQuestionMainModels);
                            if (blankflag) {
                                // 减去已经抽到题的数量
                                questionCount = questionCount - examQuestionMainModels.size();
                            } else {
                                for (int i = 0; i < examQuestionMainModels.size(); i++) {
                                    //加日志
                                    if (examQuestionMainModels.get(i) == null) {
                                        log.warn("设置得分时examQuestionMainModels.get(i) is null,examineeId-{},courseId-{}, templateId-{}, operator-{}", examineeId, courseId, templateId, operator);
                                        continue;
                                    }
                                    //加判空处理
                                    if (examQuestionMainModels.get(i) != null && !"[]".equals(examQuestionMainModels.get(i))) {
                                        // 按空抽题--减去已经抽到题的数量
                                        questionCount -= examQuestionMainModels.get(i).getOptionCount();
                                    }
                                }
                            }
                            // 题没抽够，走补偿抽题
                            if (questionCount > 0) {
                                log.warn("所选章节[" + chapter + "]题库内题目数量不足,请检查配置,将进行补偿抽题,题型Id=" + templateQuestionTypeId +
                                        " 抽出题目数量=" + examQuestionMainModels.size() + " 所需抽题数量=" + questionCount + templateExamineeCourseId);
                            }

                        } else if (randomType == 1) {
                            //章节均匀抽题。同上, 先从既定章节的其他难度等级抽题
                            if ("随机".equals(chapter)) {
                                subChapterMap = chapterMap;
                            } else {
                                subChapterMap = new LinkedHashMap<>();
                                for (Map.Entry<String, Integer> entry : chapterMap.entrySet()) {
                                    if (chapters.contains(entry.getKey())) {
                                        subChapterMap.put(entry.getKey(), entry.getValue());
                                    }
                                }
                            }
                            // 按规则章节随机抽题
                            examQuestionMainModels = takeChapterQuestion(courseId, templateQuestionTypeId, subChapterMap, degrees, mainMap, questionCount, blankflag, alreadyQuestionMainList);

                            //给抽到的题设置得分
                            for (int i = 0; i < examQuestionMainModels.size(); i++) {
                                //加日志
                                if (examQuestionMainModels.get(i) == null) {
                                    log.warn("设置得分时examQuestionMainModels.get(i) is null,examineeId-{},courseId-{}, templateId-{}, operator-{}", examineeId, courseId, templateId, operator);
                                    continue;
                                }
                                //加判空处理
                                if (examQuestionMainModels.get(i) != null && !"[]".equals(examQuestionMainModels.get(i))) {
                                    if (blankflag == true) {
                                        examQuestionMainModels.get(i).setScore(smallQuestionScore);
                                    } else {
                                        //按空给填空题每个小题赋分
                                        examQuestionMainModels.get(i).setScore(examQuestionMainModels.get(i).getOptionCount() * smallQuestionScore);
                                    }
                                }
                            }
                            //将抽出的题加入已抽题集合.
                            alreadyQuestionMainList.addAll(examQuestionMainModels);
                            if (blankflag) {
                                questionCount = questionCount - examQuestionMainModels.size();
                            } else {
                                for (int i = 0; i < examQuestionMainModels.size(); i++) {
                                    //加日志
                                    if (examQuestionMainModels.get(i) == null) {
                                        log.warn("设置得分时examQuestionMainModels.get(i) is null,examineeId-{},courseId-{}, templateId-{}, operator-{}", examineeId, courseId, templateId, operator);
                                        continue;
                                    }
                                    //加判空处理
                                    if (examQuestionMainModels.get(i) != null && !"[]".equals(examQuestionMainModels.get(i))) {
                                        questionCount -= examQuestionMainModels.get(i).getOptionCount();
                                    }
                                }
                            }

                            if (questionCount > 0) {
                                log.warn("所选章节[" + chapter + "]题库内题目数量不足,请检查配置,将进行补偿抽题,题型Id=" + templateQuestionTypeId +
                                        " 抽出题目数量=" + examQuestionMainModels.size() + " 所需抽题数量=" + questionCount + templateExamineeCourseId);
                            }
                        }

                        //endregion

                        //region 有自定义时补偿抽题 todo 填空题按空给分时补偿机制待完善 --任蒙蒙
                        if (questionCount > 0) {
                            List<Integer> allDegrees = new ArrayList<>();
                            allDegrees.addAll(Arrays.asList(new Integer[]{1, 2, 3, 0}));
                            if (questionCount > 0) {
                                allDegrees.removeAll(degrees);
                                examQuestionMainModels = takeChapterQuestion(courseId, templateQuestionTypeId, subChapterMap, allDegrees, mainMap, questionCount, blankflag, alreadyQuestionMainList);

                                //设置得分
                                for (int i = 0; i < examQuestionMainModels.size(); i++) {
                                    //加日志 --任蒙蒙
                                    if (examQuestionMainModels.get(i) == null) {
                                        log.warn("设置得分时examQuestionMainModels.get(i) is null,examineeId-{},courseId-{}, templateId-{}, operator-{}", examineeId, courseId, templateId, operator);
                                        continue;
                                    }
                                    //加判空处理 --任蒙蒙 --2018年12月21日22:43:06
                                    if (examQuestionMainModels.get(i) != null && !"[]".equals(examQuestionMainModels.get(i))) {
                                        if (blankflag == true) {
                                            // 按小题给赋分数
                                            examQuestionMainModels.get(i).setScore(smallQuestionScore);
                                        } else {
                                            //按空--给填空题每个小题赋分
                                            examQuestionMainModels.get(i).setScore(examQuestionMainModels.get(i).getOptionCount() * smallQuestionScore);
                                        }
                                    }
                                }

                                //将抽出的题加入集合.
                                alreadyQuestionMainList.addAll(examQuestionMainModels);
                                if (blankflag) {
                                    // 减去已抽到题的数量
                                    questionCount = questionCount - examQuestionMainModels.size();
                                } else {
                                    //按空抽题时候， 减去填空题的空数
                                    for (int i = 0; i < examQuestionMainModels.size(); i++) {
                                        //加日志
                                        if (examQuestionMainModels.get(i) == null) {
                                            log.warn("设置得分时examQuestionMainModels.get(i) is null,examineeId-{},courseId-{}, templateId-{}, operator-{}", examineeId, courseId, templateId, operator);
                                            continue;
                                        }
                                        //加判空处理
                                        if (examQuestionMainModels.get(i) != null && !"[]".equals(examQuestionMainModels.get(i))) {
                                            questionCount -= examQuestionMainModels.get(i).getOptionCount();
                                        }
                                    }
                                }

                            }
                            // 题没有抽够，走补偿机制
                            if (questionCount > 0) {
                                //从剩余的章节范围重新抽题(如果原来已经是"随机",allChapters.removeAll(chapters)后allChapters将变为空,不影响程序执行)
                                LinkedHashMap<String, Integer> remainChapterMap = new LinkedHashMap<>();
                                //去除已抽到的章节
                                for (Map.Entry<String, Integer> entry : chapterMap.entrySet()) {
                                    if (!subChapterMap.containsKey(entry.getKey())) {
                                        remainChapterMap.put(entry.getKey(), entry.getValue());
                                    }
                                }

                                List<Integer> degreeschapter = new ArrayList<>();
                                degreeschapter.addAll(Arrays.asList(new Integer[]{1, 2, 3, 0}));
                                // 走抽题方法，按章节随机抽题
                                examQuestionMainModels = takeChapterQuestion(courseId, templateQuestionTypeId, remainChapterMap, degreeschapter, mainMap, questionCount, blankflag, alreadyQuestionMainList);

                                //给返回的题设置得分
                                for (int i = 0; i < examQuestionMainModels.size(); i++) {
                                    //加日志
                                    if (examQuestionMainModels.get(i) == null) {
                                        log.warn("设置得分时examQuestionMainModels.get(i) is null,examineeId-{},courseId-{}, templateId-{}, operator-{}", examineeId, courseId, templateId, operator);
                                        continue;
                                    }
                                    //加判空处理
                                    if (examQuestionMainModels.get(i) != null && !"[]".equals(examQuestionMainModels.get(i))) {
                                        if (blankflag == true) {
                                            examQuestionMainModels.get(i).setScore(smallQuestionScore);
                                        } else {
                                            //给填空题每个小题赋分
                                            examQuestionMainModels.get(i).setScore(examQuestionMainModels.get(i).getOptionCount() * smallQuestionScore);
                                        }
                                    }
                                }

                                //将抽出的题加入已抽题集合.
                                alreadyQuestionMainList.addAll(examQuestionMainModels);
                                if (blankflag) {
                                    // 减去已经抽到题的数量
                                    questionCount = questionCount - examQuestionMainModels.size();
                                } else {
                                    // 按空抽题--减去已经抽到题的空数
                                    for (int i = 0; i < examQuestionMainModels.size(); i++) {
                                        //加日志
                                        if (examQuestionMainModels.get(i) == null) {
                                            log.warn("设置得分时examQuestionMainModels.get(i) is null,examineeId-{},courseId-{}, templateId-{}, operator-{}", examineeId, courseId, templateId, operator);
                                            continue;
                                        }
                                        //加判空处理
                                        if (examQuestionMainModels.get(i) != null && !"[]".equals(examQuestionMainModels.get(i))) {
                                            questionCount -= examQuestionMainModels.get(i).getOptionCount();
                                        }
                                    }
                                }
                            }
                        }
                        //endregion
                        // 走完补偿机制后，抽题数量仍然不足
                        if (questionCount > 0) {
                            log.error("扩大范围重抽题失败! 题库内题目数量不足,请检查配置,将进行补偿抽题,题型Id=" + templateQuestionTypeId +
                                    " 抽出题目数量=" + examQuestionMainModels.size() + " 所需抽题数量=" + questionCount + templateExamineeCourseId);
                        }

                    }
                }
                //endregion

                //endregion
            }
            //endregion

            //声明实体，用于保存题型描述和题干信息
            ExamTemPaperQuestionTypeModel examTemPaperQuestionTypeModel = new ExamTemPaperQuestionTypeModel();
            //添加该题型的数据
            //添加该题型基本信息
            examTemPaperQuestionTypeModel.getQuestionCode();
            //设置题型基本信息
            BeanUtils.copyProperties(templateQuestionTypeModel, examTemPaperQuestionTypeModel);

            //方便看错误日志--任蒙蒙 2018年12月20日16:25:55
            if (CollectionUtils.isEmpty(alreadyQuestionMainList)) {
                log.warn("模板随机抽题--该考试此题型没有抽到题，模板明细该题型id为:{}", templateQuestionTypeId);
                break;
            }

            //region 3.4 对抽出来的题做相应处理-任蒙蒙--2018年12月20日
            if (alreadyQuestionMainList != null && alreadyQuestionMainList.size() > 0) {

                //region 将混合题（题型code：17）和计算选择题（题型code：6）的子题加上题型名称和题型Code,方便前端显示 --任蒙蒙
                if (examTemPaperQuestionTypeModel.getQuestionCode() == 17 || examTemPaperQuestionTypeModel.getQuestionCode() == 6) {
                    List<QuestionTypeModel> questionTypeModels = questionTypeService.queryAllQuestionType();
                    if (questionTypeModels == null) {
                        log.warn("模板随机抽题--从题库题型表查询为空（混合题和计算选择题用）为空");
                        continue;
                    }
                    // Map<id, QuestionTypeModel>
                    Map<String, QuestionTypeModel> questionTypeModelMap = questionTypeModels.stream().collect(Collectors.toMap(model -> model.getId(), model -> model));
                    for (QuestionMainModel questionMainModels : alreadyQuestionMainList) {
                        if (questionMainModels == null) {
                            log.warn("模板随机抽题--该考试配的混合题中没有该题，examineeId-{},courseId-{}, templateId-{}, operator-{}", examineeId, courseId, templateId, operator);
                            continue;
                        }
                        //获得混合题父题的id
                        String parentQuestionId = questionMainModels.getQuestionId();
                        //获得混合题的子题
                        List<QuestionMainModel> questionSubModelsList = questionMainModels.getQuestionMainModelList();
                        // if (questionSubModelsList == null || questionSubModelsList.size() == 0) {
                        if (CollectionUtils.isEmpty(questionSubModelsList)) {
                            log.warn("模板随机抽题--该考试配的混合题没有子题，父题id为:{}", parentQuestionId);
                            continue;
                        }

                        //把子题赋给父题
                        // 查询子题对应的题型名称
                        for (QuestionMainModel questionSubModels : questionSubModelsList) {
                            if (questionSubModels != null) {
                                //获取子题的题型id
                                String questionTypeId = questionSubModels.getQuestionTypeId();
                                if (questionTypeId == null) {
                                    log.warn("questionTypeId is null,父题id为parentQuestionId-{}", parentQuestionId);
                                    continue;
                                }
                                QuestionTypeModel questionTypeModel = questionTypeModelMap.get(questionTypeId);
                                String questionSubTypeName = questionTypeModel.getQuestionTypeName();
                                String questionSubCode = questionTypeModel.getQuestionCode();
                                questionSubModels.setQuestionTypeName(questionSubTypeName);
                                questionSubModels.setCode(questionSubCode);
                            }
                        }
                    }
                }
                //endregion

            }
            //endregion

            //添加该题型试题信息
            examTemPaperQuestionTypeModel.setQuestionMainModelList(alreadyQuestionMainList);
            //添加该题型
            paperQuestionTypeList.add(examTemPaperQuestionTypeModel);

        }
        //endregion

        //region 4.设置试卷和试题的基本信息
        //设置试卷基本信息
        BeanUtils.copyProperties(templateDetailInfo.getTemplateModel(), examPaperModel);
        examPaperModel.setTemplateId(templateDetailInfo.getTemplateModel().getId());
        //设置试题信息
        examPaperModel.setPaperQuestionTypeList(paperQuestionTypeList);
        //endregion

        //region 5.对题干顺序赋值并排序,根据分数大小为各个小题的顺序赋值,对试卷上各个大题进行排序
        for (ExamTemPaperQuestionTypeModel typeModel : examPaperModel.getPaperQuestionTypeList()) {
            Collections.sort(typeModel.getQuestionMainModelList(), new Comparator<QuestionMainModel>() {
                @Override
                public int compare(QuestionMainModel o1, QuestionMainModel o2) {
                    //按照升序排序
                    return o1.getScore().compareTo(o2.getScore());
                }
            });
            //对题序进行赋值
            for (int k = 0; k < typeModel.getQuestionMainModelList().size(); k++) {
                QuestionMainModel questionMainModel = typeModel.getQuestionMainModelList().get(k);
//                //加判空处理
                if (questionMainModel != null) {
                    typeModel.getQuestionMainModelList().get(k).setQuestionMainOrder(k + 1);
                }
            }
            typeModel.getQuestionMainModelList().forEach((e) -> {
                if (e.getQuestionMainModelList() != null && e.getQuestionMainModelList().size() != 0) {
                    //对每个大题（题型）的顺序进行赋值，题号
                    e.getQuestionMainModelList().forEach((ec) -> {
                        ec.setQuestionMainOrder(ec.getChildOrder());
                    });
                }
            });
        }
        //endregion

        return examPaperModel;
    }


    private List<QuestionMainModel> getQuestionMainModelFromRedis(String courseId, String operator) {
        List<QuestionMainModel> examQuestionMainModelList = null;
        String courseKey = TEMPLATE_REDIS_INFO + "_" + courseId.trim() + "_" + operator.trim();
        //获取该题干json集合
        try {
            // 首先从redis中根据courseKey获取该课程的题库，转为List
            long startTime = System.currentTimeMillis();
            examQuestionMainModelList = (List<QuestionMainModel>) redisTemplate.opsForValue().get(courseKey);
            System.out.println("从redis获取题库时间" + (System.currentTimeMillis() - startTime));
        } catch (Exception e) {
            log.error("抽题-从redis中courseKey为--{}转换List失败", courseKey, e.getMessage());
            return null;
        }
        if (examQuestionMainModelList == null || examQuestionMainModelList.size() == 0) {
            log.warn("从redis查取该科考试试题失败,转为从题库查题,courseKey-{}", courseKey);
            //RLock lock = redissonClient.getLock("redisson:lock:stock:" + courseId + "_" + operator);
            // 这里加锁是避免多个线程同时从题库查题，一个线程查完之后放入缓存，其他线程就可以用reids中的题了
            try {
                //lock.lock(3, TimeUnit.MINUTES);
                // 查看redis中是否有该课程该老师添加的试题
                examQuestionMainModelList = (List<QuestionMainModel>) redisTemplate.opsForValue().get(courseKey);
                if (examQuestionMainModelList == null || examQuestionMainModelList.size() == 0) {
                    //得到该课程下所有题目的信息,题库的接口
                    examQuestionMainModelList = getQuestionsByCourseId(courseId, operator);
                }
            } finally {
//                if (lock.isHeldByCurrentThread()) {
//                    lock.unlock();
//                }
            }

            if (examQuestionMainModelList == null || examQuestionMainModelList.size() == 0) {
                log.error("从redis查取该科考试试题失败,之后从题库查题也失败,courseId-{},operator-{}", courseId, operator);
                return null;
            }
            if (examQuestionMainModelList != null && examQuestionMainModelList.size() > 0) {
                // 将从题库查到的所有题放入redis
                redisTemplate.opsForValue().set(courseKey, examQuestionMainModelList);
                //设置过期时间为4个小时
                redisTemplate.expire(courseKey, 3600 * 4, TimeUnit.SECONDS);
            }
        }
        return examQuestionMainModelList;
    }

    private TemplateQuestionTypeDetailModel getTemplateFromRedis(String templateId) {
        TemplateQuestionTypeDetailModel templateDetailInfo = new TemplateQuestionTypeDetailModel();
        //加一个redis,这是从前台传过来的模板规则
        //从redis获取对应的模板
        String detailKey = TEMPLATEDETAIL_REDIS_INFO + "_" + templateId;
        String detailJson = String.valueOf(redisTemplate.opsForValue().get(detailKey));

        String detailNull = "null";
        if (!detailNull.equals(detailJson) && StringUtils.hasText(detailJson)) {
            //添加try catch
            try {
                // 模板json转pojo
                templateDetailInfo = JacksonJsonUntil.jsonToPojo(detailJson, TemplateQuestionTypeDetailModel.class);
            } catch (IOException e) {
                log.error(e.getMessage(), e);
                log.error("模板随机抽题--从redis拿到的模板json转pojo失败" + detailJson, e);
            }
        } else {
            // redis中没有模板信息，转从库里查模板信息
            TemplateModel templateModel = templateService.selectTempModel(templateId);
            //方便看错误日志
            if (templateModel == null) {
                log.error("模板随机抽题--该考试模板信息不足，模板id为:{}", templateId);
                return null;
            }
            // 查到的模板信息放入模板实体
            templateDetailInfo.setTemplateModel(templateModel);
            List<TemplateDetailsModel> templateDetailsEntity = templateDetailsService.selectTempDetails(templateId);
            //方便看错误日志
            if (templateDetailsEntity == null) {
                log.error("模板随机抽题--该考试模板明细信息不足，模板id为:{}", templateId);
                return null;
            }
            templateDetailInfo.setTemplateDetailsModelList(templateDetailsEntity);
            if (templateDetailInfo != null) {
                //设置过期时间为4个小时
                try {
                    redisTemplate.opsForValue().set(detailKey, JacksonJsonUntil.objectToJson(templateDetailInfo));
                } catch (JsonProcessingException e) {
                    log.error(e.getMessage(), e);
                    log.error("模板随机抽题--模板明细信息存入redis转json失败" + templateDetailInfo, e);
                }
                redisTemplate.expire(detailKey, 3600 * 4, TimeUnit.SECONDS);
            }
        }
        return templateDetailInfo;
    }


    /**
     * 自然随机抽题
     *
     * @param courseId               课程 Id
     * @param templateQuestionTypeId 模板题型id
     * @param chapters               章节集合
     * @param degrees                难度等级集合
     * @param mainMap                所有试题集合
     * @param questionCount          试题个数
     * @return List<QuestionMainModel> 按规则抽好的试题集合
     * @author 李总，任蒙蒙
     * @since 2.0.0 2018-11-17 17:10:28
     */
    private List<QuestionMainModel> takeQuestion(String courseId, String
            templateQuestionTypeId, List<String> chapters, List<Integer> degrees, Map<String, List<QuestionMainModel>> mainMap,
                                                 int questionCount, List<QuestionMainModel> alreadyQuestionList) {
        //todo 填空题是按空抽题待改 --任蒙蒙
        List<QuestionMainModel> tmpQuestionModels = new ArrayList<>();
        if (questionCount < 1 || chapters == null || chapters.size() == 0 || degrees == null || degrees.size() == 0) {
            return tmpQuestionModels;
        }
        for (String chapterKey : chapters) {
            for (Integer degreeKey : degrees) {
                String key = courseId + "_" + templateQuestionTypeId + "_" + chapterKey + "_" + degreeKey;
                List<QuestionMainModel> examQuestionSubModels = mainMap.get(key);
                tmpQuestionModels.addAll(examQuestionSubModels);
            }
        }
        //去除重题 --任蒙蒙
        if (alreadyQuestionList != null && alreadyQuestionList.size() > 0) {
            Map<String, QuestionMainModel> map = alreadyQuestionList.stream().collect(Collectors.toMap(model -> model.getQuestionId(), model -> model));
            tmpQuestionModels.removeIf(model -> map.containsKey(model.getQuestionId()));
        }

        return shuffleTakeQuestion(tmpQuestionModels, questionCount, true);
    }

    /**
     * 随机抽题：从试题集合中抽取题目
     *
     * @param examQuestionMainModels 试题集合
     * @param questionCount          试题个数
     * @param blankflag              判断填空题是按空抽题还是按题抽题，blankflag为true时为按题抽题，为false时为按空抽题
     * @return
     * @author 李总，任蒙蒙
     * @since 2.0.0 2018-11-22 17:10:28
     */
    private List<QuestionMainModel> shuffleTakeQuestion(List<QuestionMainModel> examQuestionMainModels,
                                                        int questionCount, boolean blankflag) {
        if (questionCount <= 0 || examQuestionMainModels.size() == 0) {
            return new ArrayList<>();
        }
        List<QuestionMainModel> questionMainList = new ArrayList<>();

        Collections.shuffle(examQuestionMainModels);
        int count = Math.min(examQuestionMainModels.size(), questionCount);
        if (blankflag) {
            for (int i = 0; i < count; i++) {
                //保存抽取好的题目.
                questionMainList.add(examQuestionMainModels.get(i));
            }
        } else {
            int flag = 0;
            while (questionCount > 0 && flag < examQuestionMainModels.size()) {
                int cnt = examQuestionMainModels.get(flag).getOptionCount();
                int num = questionCount - cnt;
                if (cnt > 0 && num >= 0) {
                    //保存抽取好的题目.
                    questionMainList.add(examQuestionMainModels.get(flag));
                    questionCount -= cnt;
                }
                flag++;
            }
        }


        return questionMainList;
    }


    /**
     * 按章节均匀抽题
     *
     * @param courseId               课程id
     * @param templateQuestionTypeId 模板类型id
     * @param chapterMap             章节集合
     * @param degrees                难度等级集合
     * @param mainMap                所有试题集合
     * @param questionCount          试题个数
     * @param blankFlag              判断填空题是按空抽题还是按题抽题，blankFlag为true时为按题抽题，为false时为按空抽题
     * @return List QuestionMainModel 按章节均匀抽题的试题集合
     * @author 李总，任蒙蒙, 杨晓慧
     * @since 2.0.0 2018-11-22 17:10:28
     */
    private List<QuestionMainModel> takeChapterQuestion(String courseId, String
            templateQuestionTypeId, LinkedHashMap<String, Integer> chapterMap, List<Integer> degrees, Map<String, List<QuestionMainModel>> mainMap, Integer
                                                                questionCount, boolean blankFlag, List<QuestionMainModel> alreadyQuestionList) {
        //返回值
        List<QuestionMainModel> questionList = new ArrayList<>();
        if (questionCount < 1 || chapterMap == null || chapterMap.size() == 0 || degrees == null || degrees.size() == 0) {
            //所抽题目数小于1,直接返回
            return questionList;
        }
        //定义剩余章节数量.初始为章节总数,每次抽完一章,该值减1,直到最后一章.
        int remainChapterSize = chapterMap.size();
        //定义剩余待抽试题的数量,初始值为待抽总数,每次抽取后减去已抽数量.
        int remainCount = questionCount;
        //chapterMap已排序,按照从小到大的顺序循环抽题.
        // 每次重新计算平均值,本章题数与平均值二者取较小的值.
        for (Map.Entry<String, Integer> entry : chapterMap.entrySet()) {
            if (entry.getValue() == null || entry.getValue() == 0) {
                remainChapterSize--;
                continue;
            }
            int averageCount = Math.round(remainCount / (remainChapterSize == 0 ? 1 : remainChapterSize));
            remainChapterSize--;
            averageCount = averageCount == 0 ? (int) Math.round(Math.random()) : averageCount;
            //防止抽题抽多了.
            averageCount = Math.min(averageCount, remainCount);

            //本章题数与平均值二者取较小的值.当填空题按空抽题时，直接把空数赋给minCount --任蒙蒙，侯旭日
            int minCount = 0;
            if (blankFlag == true) {
                minCount = Math.min(entry.getValue(), averageCount);
            } else {
                minCount = averageCount;
            }

            String key;
            //抽题结果.
            List<QuestionMainModel> questionSubList;

            List<QuestionMainModel> tmpQuestionMainModels = new ArrayList<>();

            for (Integer degreeKey : degrees) {
                //难度等级随机
                key = courseId + "_" + templateQuestionTypeId + "_" + entry.getKey() + "_" + degreeKey;
                List<QuestionMainModel> examQuestionModels = mainMap.get(key);
                if (CollectionUtils.isEmpty(examQuestionModels)) {
                    examQuestionModels = new ArrayList<>();
                }
                tmpQuestionMainModels.addAll(examQuestionModels);
            }

            //去除重题
            if (alreadyQuestionList != null && alreadyQuestionList.size() > 0) {
                Map<String, QuestionMainModel> map = alreadyQuestionList.stream().collect(Collectors.toMap(model -> model.getQuestionId(), model -> model));
                tmpQuestionMainModels.removeIf(model -> map.containsKey(model.getQuestionId()));
            }

            questionSubList = shuffleTakeQuestion(tmpQuestionMainModels, minCount, blankFlag);

            //加日志处理 --任蒙蒙
            if (questionSubList == null) {
                log.warn("questionSubList is null,minCount-{},blankFlag-{}", minCount, blankFlag);
                continue;
            }
            if (blankFlag == true) {
                //按题目数量抽题
                remainCount -= questionSubList.size();
            } else {
                //按空抽题
                int cnt = 0;
                for (int i = 0; i < questionSubList.size(); i++) {
                    cnt += questionSubList.get(i).getOptionCount();
                }
                remainCount -= cnt;
            }
            questionList.addAll(questionSubList);
        }
        //抽题抽多了,从尾部去掉多余的.
        int removeCount = questionList.size() - questionCount;
        if (removeCount > 0) {
            for (int i = 0; i < removeCount; i++) {
                //每次移除最后一个元素.
                questionList.remove(questionList.size());
            }
        }

        return questionList;
    }

    /**
     * 将HashMap按照value的数量从小到大进行排序,输出为LinkedHashMap
     *
     * @param tmpChapterMap 章节map
     * @return 将HashMap按照value的数量从小到大进行排序, 输出为LinkedHashMap
     * @author 李总
     * @since 2.0.0 2018-11-23 10:54:28
     */
    public static LinkedHashMap<String, Integer> sortMap(Map<String, Integer> tmpChapterMap) {
        LinkedHashMap<String, Integer> chapterMap = new LinkedHashMap<>();
        //将map.entrySet()转换成list进行排序
        List<Map.Entry<String, Integer>> list = new ArrayList<Map.Entry<String, Integer>>(tmpChapterMap.entrySet());
        //然后通过比较器来实现排序
        Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() {
            @Override
            public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
                //升序排序
                return o1.getValue().compareTo(o2.getValue());
            }
        });
        for (Map.Entry<String, Integer> entry : list) {
            chapterMap.put(entry.getKey(), entry.getValue());
        }
        return chapterMap;

    }

    /**
     * 业务题处理去掉答案-李娜-2019年4月16日
     *
     * @param examPaperModel 试卷实体
     * @return
     */
    @Override
    public ExamPaperModel dealBusinessProblems(ExamPaperModel examPaperModel) {
        if (null == examPaperModel || examPaperModel.getPaperQuestionTypeList() == null) {
            log.warn("试卷实体examPaperModel为空！或 examPaperModel.getPaperQuestionTypeList()==null");
            return null;
        }
        // 用于判断是否为空字符串
        String answerNull = "";
        //ExamTemPaperQuestionTypeModel保存题型list
        for (ExamTemPaperQuestionTypeModel typeModel : examPaperModel.getPaperQuestionTypeList()) {
            if (typeModel.getQuestionCode() != null && typeModel.getQuestionCode().equals(16) || typeModel.getQuestionCode().equals(17)) {
                //questionMainModelList为题目实体
                if (typeModel.getQuestionMainModelList() != null) {
                    for (QuestionMainModel mainModel : typeModel.getQuestionMainModelList()) {

                        if (mainModel == null && "".equals(mainModel)) {
                            return examPaperModel;
                        }
                        if (mainModel.getAnswer() == null || "".equals(mainModel.getAnswer())) {
                            break;
                        }
                        if (!mainModel.getAnswer().equals(answerNull)) {
                            try {
                                //把json 类型转成实体
                                List<BussinessAllModel> bussinessAllModels = JacksonJsonUntil.jsonToList(mainModel.getAnswer(), BussinessAllModel.class);
                                if (CollectionUtils.isEmpty(bussinessAllModels)) {
                                    continue;
                                }
                                //得到不含答案的业务题(remove业务题)
                                //得到不含答案的业务题(remove业务题)
                                for (BussinessAllModel bussinessAllModels1L : bussinessAllModels) {
                                    bussinessAllModels1L.setBussinessAllList(null);
                                }
                                mainModel.setBussinessAllModels(bussinessAllModels);
                            } catch (IOException e) {
                                log.error("业务题处理失败,考试id-{},题型id-{}", examPaperModel.getExaminationId(), mainModel.getQuestionId(), e);
                                continue;
                            }
                        }
                    }

                    for (QuestionMainModel mainModel : typeModel.getQuestionMainModelList()) {
                        if (mainModel != null && mainModel.getQuestionMainModelList() != null) {
                            //针对填题的业务题
                            String answerSubNull = "";
                            for (QuestionMainModel questionMainModel : mainModel.getQuestionMainModelList()) {
                                if (questionMainModel != null && questionMainModel.getCode() != null && questionMainModel.getCode().equals("16")) {

                                    if (questionMainModel.getAnswer() != null && !questionMainModel.getAnswer().equals(answerSubNull)) {
                                        try {
                                            List<BussinessAllModel> bussinessAllSubModels = JacksonJsonUntil.jsonToList(questionMainModel.getAnswer(), BussinessAllModel.class);
                                            if (CollectionUtils.isEmpty(bussinessAllSubModels)) {
                                                continue;
                                            }
                                            //得到不含答案的业务题(remove业务题)
                                            //得到不含答案的业务题(remove业务题)
                                            for (BussinessAllModel bussinessAllModels1L : bussinessAllSubModels) {
                                                bussinessAllModels1L.setBussinessAllList(null);
                                            }
                                            questionMainModel.setBussinessAllModels(bussinessAllSubModels);
                                        } catch (IOException e) {
                                            log.error("业务题处理失败,考试id-{},题型id-{}", examPaperModel.getExaminationId(), questionMainModel.getQuestionId(), e);
                                            continue;
                                        }
                                    }
                                }
                            }
                        }

                    }
                }
            }
        }
        return examPaperModel;
    }

    @Override
    public int getExamDuration(String examId) {
        return examinationService.selfindExamDuration(examId);
    }

    /**
     * 从答题记录中查询该考生的试卷
     *
     * @param examineeId 考生id
     * @param templateId 模版id
     * @return
     * @Author 李娜
     */
    @Override
    public ExamPaperModel queryPaperAndRecord(String examineeId, String templateId) {
        QuestionMainModel mainModel = new QuestionMainModel();
        ExamPaperModel examPaperModel = new ExamPaperModel();

        // 查询模板信息和模板详情信息
        TemplateModel templateModel = templateService.selectTempModel(templateId);
        BeanUtils.copyProperties(templateModel, examPaperModel);
        List<TemplateDetailsModel> templateDetailsModels = templateDetailsService.selectTempDetails(templateId);
        Map<String, TemplateDetailsModel> templateDetailsModelMap = new HashMap<>();
        for (TemplateDetailsModel templateDetailsModel : templateDetailsModels) {
            templateDetailsModelMap.put(templateDetailsModel.getQuestionTypeId(), templateDetailsModel);
        }

        //2.根据试卷id和学生id查询题干信息,只有父id
        List<QuestionMainModel> mainDetailList = paperRecordService.selectMainInfoByPaperRecord(templateId, examineeId);
        //所有子题
        List<QuestionMainModel> questionSubModelsList = paperRecordService.selectQuestionByChildId(templateId, examineeId);

        // 存放父题的map
        Map<String, QuestionMainModel> questionMainModelMap = new HashMap<>(mainDetailList.size() * 2);
        if (CollectionUtils.isEmpty(mainDetailList)) {
            log.warn("queryPaperAndRecord method , mainDetailList is null 查询题干信息,考生id-{} 模板id-{}", examineeId, templateId);
            return null;
        } else {
            for (QuestionMainModel questionMainModel : mainDetailList) {
                questionMainModelMap.put(questionMainModel.getQuestionId(), questionMainModel);
                //分割考生答案进行回显
                if (questionMainModel.getStudentAnswer() != null) {
                    String[] answerArray = new String[0];
                    try {
                        answerArray = questionMainModel.getStudentAnswer().split("\\|");
                    } catch (Exception e) {
                        log.error("题型id-{},题id-{},考生id-{},模板id-{},学生数组分割error-{}", questionMainModel.getQuestionTypeId(), questionMainModel.getQuestionId(), examineeId, templateId, e);
                        answerArray[0] = "";
                    }
                    questionMainModel.setStudentAnswerArray(answerArray);
                }
            }
        }

        if (questionSubModelsList != null) {
            // 把子题拼到父题干下
            for (QuestionMainModel questionSubModel : questionSubModelsList) {
                //分割考生答案
                if (questionSubModel != null && questionSubModel.getStudentAnswer() != null) {
                    String[] answerArray = new String[0];
                    try {
                        answerArray = questionSubModel.getStudentAnswer().split("\\|");
                    } catch (Exception e) {
                        log.error("题型id-{},题id-{},考生id-{},模板id-{},学生数组分割,error-{}", questionSubModel.getQuestionTypeId(), questionSubModel.getQuestionId(), examineeId, templateId, e);
                        answerArray[0] = "";
                    }
                    questionSubModel.setStudentAnswerArray(answerArray);
                }
                mainModel = questionMainModelMap.get(questionSubModel.getParentId());
                if (mainModel != null) {
                    if (!CollectionUtils.isEmpty(mainModel.getQuestionMainModelList())) {
                        mainModel.getQuestionMainModelList().add(questionSubModel);
                    } else {
                        List<QuestionMainModel> questionMainModels = new ArrayList<>();
                        questionMainModels.add(questionSubModel);
                        mainModel.setQuestionMainModelList(questionMainModels);
                    }
                }
            }

            // questionMainMap中key为题型，value为该题型对应的所有题干
            Map<String, List<QuestionMainModel>> questionMainMap = new HashMap<>();
            for (QuestionMainModel questionMainModel : mainDetailList) {
                if (CollectionUtils.isEmpty(questionMainMap.get(questionMainModel.getQuestionTypeId()))) {
                    List<QuestionMainModel> questionMainModels = new ArrayList<>();
                    questionMainModels.add(questionMainModel);
                    questionMainMap.put(questionMainModel.getQuestionTypeId(), questionMainModels);
                } else {
                    questionMainMap.get(questionMainModel.getQuestionTypeId()).add(questionMainModel);
                }
            }

            List<ExamTemPaperQuestionTypeModel> paperQuestionTypeList = new ArrayList<>();
            for (Map.Entry<String, List<QuestionMainModel>> entry : questionMainMap.entrySet()) {
                if (templateDetailsModelMap.containsKey(entry.getKey())) {
                    ExamTemPaperQuestionTypeModel examTemPaperQuestionTypeModel = new ExamTemPaperQuestionTypeModel();
                    BeanUtils.copyProperties(templateDetailsModelMap.get(entry.getKey()), examTemPaperQuestionTypeModel);
                    examTemPaperQuestionTypeModel.setQuestionMainModelList(entry.getValue());
                    paperQuestionTypeList.add(examTemPaperQuestionTypeModel);
                }
            }
            examPaperModel.setPaperQuestionTypeList(paperQuestionTypeList);
        }
        return examPaperModel;
    }

    /**
     * 对查询出的试卷的题型和题干进行排序-2019年4月16日
     *
     * @param examPaperModel 试卷实体
     * @return
     */
    @Override
    public ExamPaperModel getPaperSort(ExamPaperModel examPaperModel) {
        if (ObjectUtils.isEmpty(examPaperModel) || ObjectUtils.isEmpty(examPaperModel.getPaperQuestionTypeList())) {
            log.warn("getPaperSort执行失败，试卷实体examPaperModel is null!");
            return null;
        }

        //题型顺序
        if (examPaperModel.getPaperQuestionTypeList() != null && examPaperModel.getPaperQuestionTypeList().size() > 0) {

            // 对题型进行排序，按照模板配置的题型顺序进行排序-2019年4月16日
            try {
                examPaperModel.getPaperQuestionTypeList().sort((o1, o2) -> o1.getQuestionTypeOrder().compareTo(o2.getQuestionTypeOrder()));
            } catch (Exception e) {
                log.info("getQuestionTypeOrder为空}");
            }

            //循环每一个题型，对题型中的题干进行排序，题干顺序在抽题时进行的赋值-2019年4月16日
            for (ExamTemPaperQuestionTypeModel examTemPaperQuestionTypeModel : examPaperModel.getPaperQuestionTypeList()) {
                if (examTemPaperQuestionTypeModel.getQuestionMainModelList() != null && examTemPaperQuestionTypeModel.getQuestionMainModelList().size() > 0) {
                    try {
                        //对父题干进行排序
                        examTemPaperQuestionTypeModel.getQuestionMainModelList().sort((o3, o4) -> (o3.getQuestionMainOrder().compareTo(o4.getQuestionMainOrder())));
                    } catch (Exception e) {
                        log.error("getQuestionTypeOrder为空,examTemPaperQuestionTypeid-{}", examTemPaperQuestionTypeModel.getQuestionTypeId());
                    }
                }

                if (examTemPaperQuestionTypeModel.getQuestionMainModelList() != null) {
                    for (QuestionMainModel questionMainModel : examTemPaperQuestionTypeModel.getQuestionMainModelList()) {
                        if (questionMainModel.getQuestionSubEntityList() != null && questionMainModel.getQuestionSubEntityList().size() > 0) {
                            //对父题干选项进行排序
                            try {
                                questionMainModel.getQuestionSubEntityList().sort((o5, o6) -> (o5.getOptionOrder().compareTo(o6.getOptionOrder())));
                            } catch (Exception e) {
                                log.error("OptionOrder为空,examTemPaperQuestionTypeid-{}", examTemPaperQuestionTypeModel.getQuestionTypeId());
                            }
                        }

                        // 有子题
                        if (questionMainModel.getQuestionMainModelList() != null) {
                            for (QuestionMainModel mainModel : questionMainModel.getQuestionMainModelList()) {
                                if (mainModel.getQuestionMainModelList() != null && mainModel.getQuestionMainModelList().size() > 0) {
                                    //对子题干进行排序-2019年4月16日
                                    try {
                                        mainModel.getQuestionMainModelList().sort((o7, o8) -> (o7.getQuestionMainOrder().compareTo(o8.getQuestionMainOrder())));
                                    } catch (Exception e) {
                                        log.error("QuestionMainOrder为空,examTemPaperQuestionTypeid-{}", examTemPaperQuestionTypeModel.getQuestionTypeId());
                                    }
                                }

                                if (mainModel.getQuestionSubEntityList() != null) {
                                    try {
                                        //对子题选项进行排序-2019年4月16日
                                        mainModel.getQuestionSubEntityList().sort((o9, o10) -> (o9.getOptionOrder().compareTo(o10.getOptionOrder())));
                                    } catch (Exception e) {
                                        log.error("OptionOrder为空,examTemPaperQuestionTypeid-{}", examTemPaperQuestionTypeModel.getQuestionTypeId());
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        return examPaperModel;
    }

    /**
     * 学生抽到试题后将抽出的试题插入到答题记录表中
     *
     * @param examineeId     考生id
     * @param examinationId  考试id
     * @param examPaperModel 试卷详情model
     * @return
     * @Athor 李娜
     */
    @Override
    @Async
    @Transactional
    public List<PaperRecordEntity> insertAllPaperRecord(String examineeId, String examinationId, ExamPaperModel
            examPaperModel) {
        if (examPaperModel == null) {
            log.warn("试卷详情examPaperModel is null 考生id-{}！ 考试id-{}", examineeId, examinationId);
            return null;
        }

        if (examPaperModel.getPaperQuestionTypeList() == null) {
            log.warn("试卷题型为空！考生id-{}！ 考试id-{},模板id-{}, 课程id-{}", examineeId, examinationId, examPaperModel.getTemplateId(), examPaperModel.getCourseId());
            return null;
        }

        List<PaperRecordEntity> recordEntityList = new ArrayList<>();
        List<QuestionTypeModel> questionTypeModels = questionTypeService.queryAllQuestionType();
        Map<String, String> questionTypeMap = new HashMap<>();
        for (QuestionTypeModel questionTypeModel : questionTypeModels) {
            questionTypeMap.put(questionTypeModel.getQuestionTypeName(), questionTypeModel.getId());
        }

        // 递归实现把所有的题插入到答题记录表
        for (ExamTemPaperQuestionTypeModel questionTypeModel : examPaperModel.getPaperQuestionTypeList()) {
            List<PaperRecordEntity> recordEntities = queryPaperRecord(examineeId, questionTypeModel.getQuestionMainModelList(), examPaperModel, questionTypeMap);
            recordEntityList.addAll(recordEntities);
        }

        //判断答题记录是否为null或者存在答题记录，则不执行插入答题记录操作
        int result = 0;
        if (recordEntityList != null && recordEntityList.size() > 0) {
            // TODO: 2019-07-09 是否需要加trycatch？-李娜
            result = paperRecordService.insertAllPaperRecord(recordEntityList, examineeId, examinationId);
            if (result > 0) {
                return recordEntityList;
            } else {
                log.error("试卷插入答题记录表失败，examineeId{}，examinationId{}", examineeId, examinationId);
                return null;
            }
        }
        return null;
    }

    /**
     * 递归实现将试卷插入到答题记录表
     *
     * @param questionMainModels
     * @param examPaperModel
     * @return
     * @Author 李娜
     */
    double childScore = 0.0;

    public List<PaperRecordEntity> queryPaperRecord(String examineeId, List<QuestionMainModel> questionMainModels, ExamPaperModel
            examPaperModel, Map<String, String> questionTypeMap) {
        List<PaperRecordEntity> recordEntityList = new ArrayList<>();
        Date date = DateTimeUtils.dateFormat(new Date());

        for (QuestionMainModel mainModel : questionMainModels) {
            double score = 0.0;
            if (ObjectUtils.isEmpty(mainModel.getParentId())) {
                //获取每题分值（自定义和随机，涉及模版明细表和模版自定义表）
                if (mainModel.getScore() == null || "".equals(mainModel.getScore())) {
                    score = 0;
                } else {
                    score = mainModel.getScore();
                }

                if (!ObjectUtils.isEmpty(questionTypeMap.get("计算选择题")) && questionTypeMap.get("计算选择题").equals(mainModel.getQuestionTypeId())) {
                    if (!CollectionUtils.isEmpty(mainModel.getQuestionMainModelList())) {
                        try {
                            childScore = (mainModel.getScore() / mainModel.getQuestionMainModelList().size());
                        } catch (Exception e) {
                            log.error("计算选择题单个分数计算出错,默认标准分数为0,题型id-{},题id-{},考生id-{},考试id-{},模板id-{}, 课程id-{},出错信息-{}", mainModel.getQuestionTypeId(), mainModel.getQuestionId(), examineeId, examPaperModel.getExaminationId(), examPaperModel.getTemplateId(), examPaperModel.getCourseId(), e);
                            childScore = 0.0;
                        }
                    }
                }
            }

            /**
             * 有子题的题型分为三类，计算选择题，业务题
             * 计算选择题题的子题类型为单选题，混合题包括填空 4分和业务题6分，数据库没有设置，写死的值（模板需要完善）-李娜-2019年7月9日
             */
            if (!ObjectUtils.isEmpty(mainModel.getParentId())) {
                if (!ObjectUtils.isEmpty(questionTypeMap.get("填空题")) && mainModel.getQuestionTypeId().equals(questionTypeMap.get("填空题"))) {
                    score = 4.0;
                    mainModel.setScore(score);
                }
                if (!ObjectUtils.isEmpty(questionTypeMap.get("业务题")) && mainModel.getQuestionTypeId().equals(questionTypeMap.get("业务题"))) {
                    score = 6.0;
                    mainModel.setScore(score);
                }
                if (!ObjectUtils.isEmpty(questionTypeMap.get("单选题")) && mainModel.getQuestionTypeId().equals(questionTypeMap.get("单选题"))) {
                    score = childScore;
                    mainModel.setScore(score);
                }
            }

            PaperRecordEntity recordEntity = new PaperRecordEntity();
            BeanUtils.copyProperties(examPaperModel, recordEntity);
            BeanUtils.copyProperties(mainModel, recordEntity);
            recordEntity.setId(IdWorker.getIdStr());
            recordEntity.setExamClassifyId(examPaperModel.getExamclassifyId());
            recordEntity.setExamineeId(examineeId);
            recordEntity.setStandardScore(score);
            recordEntity.setMarkStatus(0);
            recordEntity.setCorrectAnswer(mainModel.getAnswer());
            recordEntity.setQuestionOrder(mainModel.getQuestionMainOrder());
            recordEntity.setCreateTime(date);
            recordEntity.setUpdateTime(date);
            mainModel.setPaperRecordId(recordEntity.getId());

            if (!CollectionUtils.isEmpty(mainModel.getQuestionMainModelList())) {
                for (QuestionMainModel questionMainModel : mainModel.getQuestionMainModelList()) {
                    questionMainModel.setParentId(mainModel.getQuestionId());
                }
                recordEntityList.addAll(queryPaperRecord(examineeId, mainModel.getQuestionMainModelList(), examPaperModel, questionTypeMap));
            }
            recordEntityList.add(recordEntity);
        }
        return recordEntityList;
    }

    /**
     * 判断二次登陆密码是否正确
     *
     * @param password 二次登陆密码
     * @return 布尔值
     * @author 王雪芬
     * @since 2.0.0 2018年11月26日12:14:37
     */
    @Override
    public boolean getSecordLoginPassword(String password) {
        if (secondLoginPassword.equals(password)) {
            return true;
        } else {
            return false;
        }
    }

    @Override
    @Transactional(rollbackOn = Exception.class)
    public boolean updateStateExamStudent(String examineeId, String ip, Date getStemDate) {
        ExamineeEntity examineeEntity = new ExamineeEntity();
        examineeEntity.setId(examineeId);
        examineeEntity.setStudentIp(ip);
        examineeEntity.setStudentExamState(1);
        examineeEntity.setGetQuestionTime(getStemDate);
        //抽题时间+考试时长=理论交卷时间
        boolean update = examineeService.updateById(examineeEntity);
        return update;
    }


    @Transactional(rollbackOn = Exception.class)
    @Override
    public boolean updateExamPaperRecord(PaperOnlineRecordModel paperOnlineRecordModel) {
        if (paperOnlineRecordModel == null) {
            log.warn("更新答题记录paperOnlineRecordModel is null ");
            return false;
        }
        if (StringUtils.isEmpty(paperOnlineRecordModel.getPaperRecordId())) {
            log.warn("更新答题记录:试题id不能为空 ExamineeId- {},paperOnlineRecordModel-{} ", paperOnlineRecordModel.getExamineeId(), paperOnlineRecordModel);
            return false;
        }

        //用于判断是否为空字符串
        String[] studentAnswerArrayTrim = paperOnlineRecordModel.getStudentAnswerArray();
        //去除前端传过来的show  not element 元素
        List<String> studentAnswerList = new ArrayList<>();
        if (studentAnswerArrayTrim != null) {
            for (int i = 0; i < studentAnswerArrayTrim.length; i++) {
                if (studentAnswerArrayTrim[i] != null) {
                    studentAnswerList.add(studentAnswerArrayTrim[i]);
                }
                if (studentAnswerArrayTrim[i] == null) {
                    studentAnswerList.add("");
                }
            }
        }
        if (studentAnswerList != null) {
            String[] studentAnswerArray = (String[]) studentAnswerList.toArray(new String[studentAnswerList.size()]);
            //数组之间使用|分割
            //判分需要-判分返回的结果是不一样的
            paperOnlineRecordModel.setStudentAnswerOnline(String.join("|", studentAnswerArray));
            //插入答题记录需要
            paperOnlineRecordModel.setStudentAnswerS(String.join("|", StringUtils.trimArrayElements(studentAnswerArray)));
        }
        boolean judgeScore = false;
        //简单题和名词解释题不走自动判分,操作题
        if (paperOnlineRecordModel.getQuestionCode() != null && !paperOnlineRecordModel.getQuestionCode().equals("11") && !paperOnlineRecordModel.getQuestionCode().equals("20") && !paperOnlineRecordModel.getQuestionCode().equals("21")) {
            try {
                judgeScore = judgeTaskService.automaticJudge(paperOnlineRecordModel);
            } catch (Exception e) {
                log.error("考生判分异常,考生id:{} ,考试id-{},paperRecordId-{}", paperOnlineRecordModel.getExamineeId(), paperOnlineRecordModel.getExaminationId(), paperOnlineRecordModel.getPaperRecordId(), e);
            }
            if (judgeScore == false) {
                log.warn("考生判分失败,考生id:{} ,考试id-{},paperRecordId-{}", paperOnlineRecordModel.getExamineeId(), paperOnlineRecordModel.getExaminationId(), paperOnlineRecordModel.getPaperRecordId());
            }
        }
        //查询答题的记录
        PaperRecordEntity paperRecordEntity = paperRecordService.getById(paperOnlineRecordModel.getPaperRecordId());

        if (paperRecordEntity != null && paperRecordEntity.getIsDelete() != 1) {
            //更改判分状态
            if (judgeScore == true) {
                paperRecordEntity.setMarkStatus(1);
            }
            //考评专用学生答案
            if (paperOnlineRecordModel.getStudentAnswerOnline() != null && !paperOnlineRecordModel.getQuestionCode().equals("21")) {
                //更新学生分数
                paperRecordEntity.setScore(paperOnlineRecordModel.getScore());
                if (paperOnlineRecordModel.getScore() == null) {
                    log.warn("更新学生分数is null, paperOnlineRecordModel 信息-{}", paperOnlineRecordModel);
                }
                paperRecordEntity.setStudentAnswerArrayStr(paperOnlineRecordModel.getStudentAnswerOnline());
                //更新答题记录的来源//（0默认值，1从在线考试跟新，2来自json导入）
                paperRecordEntity.setOrigin(1);

                int updateResult = paperRecordDao.updateById(paperRecordEntity);
                return updateResult > 0;
            }

            //一级专用
            if (paperOnlineRecordModel.getQuestionCode().equals("21")) {
                paperRecordEntity.setMarkStatus(1);
                paperRecordEntity.setScore(paperOnlineRecordModel.getScore());
                paperRecordEntity.setOrigin(1);
                int updateResult = paperRecordDao.updateById(paperRecordEntity);
                return updateResult > 0;
            }
            //学生答案可以为空,例如填空题
            log.warn("学生答案为空,考生id-{},paperRecordId-{},学生答案-{}", paperOnlineRecordModel.getExamineeId(), paperOnlineRecordModel.getPaperRecordId(), paperOnlineRecordModel.getStudentAnswerOnline());
            return true;
        }
        //查询没有对应的paperRecordId
        log.warn("查询数据库没有该学生对应的答题记录,考生id-{},paperRecordId-{}", paperOnlineRecordModel.getExamineeId(), paperOnlineRecordModel.getPaperRecordId());
        return false;
    }


    @Override
    public ItooResult queryQuestionTempleate(String courseId, String templeatId, String operator) {
        //1.2抽题 operator后加的,TODO 需要查询获取下-任蒙蒙
        ExamPaperModel examPaperModel = getPaperByTemplateRandom(templeatId, "考生id-模板使用", courseId, operator);
        if (ObjectUtils.isEmpty(examPaperModel)) {
            log.error("getPaperByTemplate查询为空,执行失败!paperId-{},examineeId-{},courseId-{},operator-{}", templeatId, "6666", courseId);
            return ItooResult.build(ItooResult.FAIL, "模板抽卷预览失败！");
        }

        //业务题处理操作需要去掉答案
        examPaperModel = dealBusinessProblems(examPaperModel);
        //排序
        getPaperSort(examPaperModel);
        return ItooResult.build(ItooResult.SUCCESS, "模板抽卷预览成功", examPaperModel);
    }


    @Override
    public ItooResult findQuestionNaire() {
        //试卷所有内容
        QuestionNaireAllInfoModel questionNaireAllInfoModel = new QuestionNaireAllInfoModel();

        //试卷基本信息  //得到问卷id
        questionNaireAllInfoModel = evaluationPaperService.queryTeEvaluationPaper();

        List<EvaluationPaperDetailModel> teEvaluationPaperDetailModels = new ArrayList<>();
        //得到指定某一个问卷所有详情(题型)
        teEvaluationPaperDetailModels = evaluationPaperDetailService.queryTeEvaluationPaperDetail(questionNaireAllInfoModel.getPaperId());

        List<EvaluationTypeModel> evaluationTypeModels = new ArrayList<>();
        //得到所有题型
        evaluationTypeModels = questionTypeService.queryEvaluationAllQuestionType();

        teEvaluationPaperDetailModels.sort((o1, o2) -> o1.getQuestionOrder().compareTo(o2.getQuestionOrder()));
        for (EvaluationPaperDetailModel teEvaluationPaperDetailModel : teEvaluationPaperDetailModels) {
            teEvaluationPaperDetailModel.getEvaluationSubModelList().sort((o3, o4) -> o3.getOptionOrder().compareTo(o4.getOptionOrder()));
        }

        List<EvaluationTypeModel> evaluationTypeModelsList = new ArrayList<>();
        List<EvaluationPaperDetailModel> teEvaluationPaperDetailList = null;
        List<EvaluationTypeModel> evaluationTypeModels1 = new ArrayList<>();

        for (EvaluationTypeModel typeModel : evaluationTypeModels) {          //问卷中的题型
            EvaluationTypeModel evaluationTypeModel = null;
            //是否匹配过
            boolean matchTypeQuestion = false;
            for (EvaluationPaperDetailModel teEvaluationPaperDetailModel : teEvaluationPaperDetailModels) {
                //试卷的题型与每一个题的题型相等
                if (typeModel.getId().equals(teEvaluationPaperDetailModel.getQuestionTypeId())) {
                    if (!matchTypeQuestion) {
                        //只有匹配上才会实例化,每一次匹配上只实例化一次
                        teEvaluationPaperDetailList = new ArrayList<>();
                        evaluationTypeModel = new EvaluationTypeModel();
                        matchTypeQuestion = true;
                    }
                    teEvaluationPaperDetailList.add(teEvaluationPaperDetailModel);
                }
            }
            //题型与题目不匹配不会set
            if (evaluationTypeModel != null) {
                evaluationTypeModel.setTeEvaluationPaperDetailModels(teEvaluationPaperDetailList);
                //如果匹配放到整个typelist下面
                evaluationTypeModels1.add(evaluationTypeModel);
            }
        }
        //最后放入整张试卷
        questionNaireAllInfoModel.setEvaluationTypeModels(evaluationTypeModels1);
        return ItooResult.build(ItooResult.SUCCESS, "调查问卷查询成功", questionNaireAllInfoModel);
    }

    /**
     * 重新抽卷-2019年4月17日-李娜
     *
     * @param examRecoverModel
     * @return
     */
    @Transactional(rollbackOn = Exception.class)
    @Override
    public ItooResult queryRecoverQuestionPerson(ExamRecoverModel examRecoverModel) {

        if (examRecoverModel.getTempleatId() == null) {
            log.warn("该考生-{},没有考试,没有模板id-{} ,examRecoverModel-{}", examRecoverModel.getExamineeId(), examRecoverModel);
        }

        if (examRecoverModel.getCourseId() == null) {
            log.warn("该考生-{},没有考试,没有课程id-{} ,examRecoverModel-{}", examRecoverModel.getExamineeId(), examRecoverModel);
        }

        if (examRecoverModel.getExamId() == null) {
            log.warn("该考生-{},没有考试,没有考生id-{} ,examRecoverModel-{}", examRecoverModel.getExamineeId(), examRecoverModel);
        }

        if (examRecoverModel.getExaminationId() == null) {
            log.warn("该考生-{},没有考试,没有考试id-{} ,examRecoverModel-{}", examRecoverModel.getExaminationId(), examRecoverModel);
        }

        //1去重reids中的数据
        //2删除答题记录表给考生的信息
        //3从新抽提
        //4存储到redis中

        ExaminationModel examinationModel = examinationService.queryRecoverExamination(examRecoverModel.getExaminationId());
        if (examinationModel == null && StringUtils.isEmpty(examinationModel.getTemplateId())) {
            log.warn("该考生-{},没有考试,没有模板id", examRecoverModel.getExamineeId());
            return ItooResult.build(ItooResult.FAIL, "该考生-{},没有考试", false);
        }

        //模板id,redis取值和赋值
        examRecoverModel.setTempleatId(examinationModel.getTemplateId());
        String kyeName = REDIS_KEY_PRO_NAME + "_" + examRecoverModel.getExamineeId() + "_" + examRecoverModel.getTempleatId() + "_" + ConstantUtils.REDIS_PAPER_NAME;
        Object examinationModel1 = redisTemplate.opsForValue().get(kyeName);

        //判断redis中没有值
        if (examinationModel1 == null) {
            log.info("reids中为空");
            //具体业务逻辑
            ExamPaperModel examPaperModel = queryRecover(examRecoverModel);
            if (examPaperModel != null) {
                return ItooResult.build(ItooResult.SUCCESS, "重新抽卷成功", true);
            }
            return ItooResult.build(ItooResult.FAIL, "重新抽卷失败", false);

        } else {
            log.info("reids有数据");
            String keyNameDelete = REDIS_KEY_PRO_NAME + "_" + examRecoverModel.getExamineeId() + "_" + examRecoverModel.getTempleatId() + "_" + ConstantUtils.REDIS_PAPER_NAME;
            Boolean delete = redisTemplate.delete(keyNameDelete);
            if (delete) {
                log.info("删除redis中的数据");
                ExamPaperModel examPaperModel = queryRecover(examRecoverModel);
                if (examPaperModel == null) {
                    return ItooResult.build(ItooResult.FAIL, "重新抽卷失败,redis中的记录没有清除", false);
                }
                return ItooResult.build(ItooResult.SUCCESS, "重新抽卷成功,清楚redis中记录", true);
            }
            return ItooResult.build(ItooResult.FAIL, "重新抽卷失败,redis中的记录没有清除", false);
        }
    }

    /**
     * 根据模版id和考生id查询试卷
     *
     * @param examineeId
     * @param templateId
     * @return
     */
    @Override
    public ItooResult queryExamination(String examineeId, String templateId) {
        ExamPaperModel examPaperModel = queryPaperAndRecord(examineeId, templateId);
        if (ObjectUtils.isEmpty(examPaperModel)) {
            log.warn("examPaperModel is null,examineeId-{},templateId-{}", examineeId, templateId);
            return null;
        }
        //业务题处理操作需要去掉答案
        examPaperModel = dealBusinessProblems(examPaperModel);
        return ItooResult.build(ItooResult.SUCCESS, "调查问卷查询成功", examPaperModel);
    }

    /**
     * @param examRecoverModel
     * @return
     */

    public ExamPaperModel queryRecover(ExamRecoverModel examRecoverModel) {
        //查询是否有答题记录
        QueryWrapper<PaperRecordEntity> paperRecordEntityQueryWrapper = new QueryWrapper<>();
        PaperRecordEntity paperRecordEntity = new PaperRecordEntity();
        paperRecordEntityQueryWrapper.eq("examinee_id", examRecoverModel.getExamineeId());
        paperRecordEntityQueryWrapper.eq("course_id", examRecoverModel.getCourseId());
        paperRecordEntityQueryWrapper.eq("template_id", examRecoverModel.getTempleatId());
        paperRecordEntityQueryWrapper.eq("examination_id", examRecoverModel.getExaminationId());
        paperRecordEntityQueryWrapper.eq("is_delete", 0);
        paperRecordEntity.setIsDelete(1);
        List<PaperRecordEntity> paperRecordEntityList = paperRecordService.list(paperRecordEntityQueryWrapper);

        //如果有答题记录假删除答题记录中的数据
        if (paperRecordEntityList != null && paperRecordEntityList.size() > 0) {
            try {
                boolean remove = paperRecordService.remove(paperRecordEntityQueryWrapper);
            } catch (Exception e) {
                log.error("重新抽卷删除答题记录失败,考生id为-{}", examRecoverModel.getExamineeId(), "错误信息", e);
            }
        } else {
            log.warn("该考生-{},答题记录表中没有数据", examRecoverModel.getExaminationId());
            return null;
        }

        //重新抽卷
        //更改考试状态为0为抽卷
        QueryWrapper<ExamineeEntity> examineeEntityQueryWrapper = new QueryWrapper<>();
        examineeEntityQueryWrapper.eq("id", examRecoverModel.getExamineeId());
        examineeEntityQueryWrapper.eq("is_delete", 0);
        List<ExamineeEntity> examineeList = examineeService.list(examineeEntityQueryWrapper);
        if (examineeList != null && examineeList.size() > 0) {
            examineeList.get(0).setStudentExamState(0);//改为学生未登录的状态
            //更新考试状态为未考试状态
            examineeService.updateById(examineeList.get(0));
        }
        //重新抽提
        return (ExamPaperModel) findPaperByStudentIdForOnlineExam(examRecoverModel.getExaminationId(), examRecoverModel.getClientIp(), examRecoverModel.getExamineeId(), null).getData();
    }

    /**
     * 修改抽到错题的考生的错题,放到redis
     *
     * @param examineeModelList 考生list
     * @param oldQuestionId     旧题Id
     * @param newQuestionId     新题Id
     * @author 任蒙蒙
     * @since 2.0.0 2018-11-17 17:10:28
     */
    @Override
    @Transactional(rollbackOn = Exception.class)
    public Boolean updateWrongQuesForExaminee(List<ExamineeModel> examineeModelList, String oldQuestionId, String newQuestionId) {

        boolean flag1 = false;

        //查找新题对应的model
        QuestionMainModel newQuestionModel = questionService.selectNewQuestionModel(newQuestionId);
        if (newQuestionModel == null) {
            log.error("修改后的新题为空,新题id为newQuestionId-{}", newQuestionId);
            return false;
        }

        //region 如果有子题,将父题对应的子题查到
        //获得混合题或计算选择题的子题--任蒙蒙
        List<QuestionMainModel> questionSubModelsList = new ArrayList<>();
        questionSubModelsList = questionService.selectSubQuestionByParentId(newQuestionId);
        if (questionSubModelsList == null) {
            log.warn("模板随机抽题--该考试没有配混合题或该考试配的混合题没有子题，父题id为:{}", newQuestionId);
        }
        //把子题赋给父题--任蒙蒙
        if (questionSubModelsList != null && questionSubModelsList.size() > 0) {
            newQuestionModel.setQuestionMainModelList(questionSubModelsList);
        }
        //endregion

        //region 循环每个考生,将新题替换旧题
        for (ExamineeModel examineeModel : examineeModelList) {

            ExamPaperModel changeQuesitonModel = new ExamPaperModel();
            //region 1. 从redis中取出该考生的答题记录
            //得到抽到错题的考生id
            String examineeId = examineeModel.getId();
            //模板id
            String templateId = examineeModel.getTemplateId();
            //题型id
            String questionTypeId = examineeModel.getQuestionTypeId();
            //加一个redis
            String keyName = REDIS_KEY_PRO_NAME + "_" + examineeId + "_" + templateId + "_" + ConstantUtils.REDIS_PAPER_NAME;

            changeQuesitonModel = (ExamPaperModel) redisTemplate.opsForValue().get(keyName);
            //endregion

            if (changeQuesitonModel == null) {

                //去答题记录表查询,TODO测试
                changeQuesitonModel = queryPaperAndRecord(examineeId, templateId);
                if (changeQuesitonModel == null) {
                    log.error("queryPaperAndRecord查询为空,执行失败!examineeId-{},paperId-{}", examineeId, templateId);
                    return false;
                }
            }
            //region 2. 把改后的新题更新paperRecord表,同时替换之前的错题记录放到redis

            //查询paperRecord表
            PaperRecordEntity paperRecordEntity = paperRecordService.selectPaperRecordId(examineeId, templateId, oldQuestionId);
            if (paperRecordEntity == null) {
                log.error("paperRecordEntity is null,examineeId-{},templateId-{},oldQuestionId-{}", examineeId, templateId, oldQuestionId);
                continue;
            }
            //更新paperRecord表
            paperRecordEntity.setQuestionId(newQuestionId);
            String paperRecordId = paperRecordEntity.getId();
            paperRecordEntity.setStudentAnswerArrayStr("");
            paperRecordEntity.setOperator(examineeId);

            if (paperRecordService.updateById(paperRecordEntity)) {
//            把改后的新题替换之前的错题记录放到redis
                //设置过期时间为4个小时
                List<ExamTemPaperQuestionTypeModel> paperQuestionTypeList = changeQuesitonModel.getPaperQuestionTypeList();
                for (ExamTemPaperQuestionTypeModel questionTypeModel : paperQuestionTypeList) {
                    if (questionTypeModel.getQuestionTypeId().equals(questionTypeId)) {
                        List<QuestionMainModel> questionMainModelList = questionTypeModel.getQuestionMainModelList();
                        for (QuestionMainModel questionMainModel : questionMainModelList) {
                            if (questionMainModel.getQuestionId().equals(oldQuestionId)) {
                                //将旧题的小题顺序questionMainOrder赋给新题
                                Integer questionMainOrder = questionMainModel.getQuestionMainOrder();
                                if (questionMainOrder != null) {
                                    newQuestionModel.setQuestionMainOrder(questionMainOrder);
                                }
                                //将旧题的小题分数questionMainOrder赋给新题
                                Double smallQuestionScore = questionMainModel.getScore();
                                if (smallQuestionScore != null) {
                                    newQuestionModel.setScore(smallQuestionScore);
                                }
                                newQuestionModel.setPaperRecordId(paperRecordId);

                                //替换旧题
                                questionMainModelList.set(questionMainModelList.indexOf(questionMainModel), newQuestionModel);
                            }
                        }
                        questionTypeModel.setQuestionMainModelList(questionMainModelList);
                    }
                }
                changeQuesitonModel.setPaperQuestionTypeList(paperQuestionTypeList);
                //业务题处理操作需要去掉答案
                dealBusinessProblems(changeQuesitonModel);
                redisTemplate.opsForValue().set(keyName, changeQuesitonModel);
                redisTemplate.expire(keyName, 3600 * 4, TimeUnit.SECONDS);
                flag1 = true;
            } else {
                flag1 = false;
            }
            //endregion
        }
        //endregion

        return flag1;
    }

    /**
     * 题库接口--根据题干Id查询当前考试是否有需要修改的题干
     *
     * @param wrongQuetionId 题干id
     * @return 布尔值
     * @author 任蒙蒙
     */
    @Override
    public Boolean getExamineeStatusChange(QuestionEntity newQuestionEntity) {

        if (newQuestionEntity == null) {
            log.error("newQuestion is null");
            return false;
        }
        String newQuestionId = newQuestionEntity.getId();
        String oldQuestionId = newQuestionEntity.getHistoryId();
        if (oldQuestionId == null || newQuestionId == null) {
            log.error("oldQuestionId is null or newQuestionId is null");
            return false;
        }
        //根据旧题的Id查询旧题题干内容
        String oldQuesitonContent = questionService.selectOldQuestion(oldQuestionId);

        if (oldQuesitonContent == null) {
            log.warn("oldQuestionContent is null or oldQuestionContentHtml is null,oldQuestionContent-{},oldQuestionContentHtml-{}", oldQuesitonContent);
        }

        //用在线考试专用的model,方便新旧题的替换
        QuestionMainModel newQuestionModel = questionService.selectNewQuestionModel(newQuestionId);
        if (newQuestionModel == null) {
            log.error("修改后的新题为空,新题id为newQuestionId-{}", newQuestionId);
            return false;
        }

        //获得混合题或计算选择题的子题--任蒙蒙
        List<QuestionMainModel> questionSubModelsList = questionService.selectSubQuestionByParentId(newQuestionId);
        if (questionSubModelsList == null) {
            log.warn("该考试没有配混合题或该考试配的混合题没有子题，父题id为:{}", newQuestionId);
        }
        //把子题赋给父题--任蒙蒙
        if (questionSubModelsList != null && questionSubModelsList.size() > 0) {
            newQuestionModel.setQuestionMainModelList(questionSubModelsList);
        }

        //region 将加载到redis的该科,该操作老师的题库中的错题替换为新题
        List<QuestionMainModel> examQuestionMainModelList = null;
        String courseId = newQuestionEntity.getCourseId();
        String operator = newQuestionEntity.getOperator();
        String courseKey = TEMPLATE_REDIS_INFO + "_" + courseId.trim() + "_" + operator.trim();

        try {
            examQuestionMainModelList = (List<QuestionMainModel>) redisTemplate.opsForValue().get(courseKey);
        } catch (Exception e) {
            log.error("redis中key为" + courseKey + "查询失败", e.getMessage());
        }
        if (examQuestionMainModelList == null) {
            log.warn("examQuestionMainModelList is null,courseKey-{}", courseKey);
        } else if (examQuestionMainModelList != null) {
            String newQuestionTypeId = newQuestionEntity.getQuestionTypeId();
            String newChapter = newQuestionEntity.getQuestionClassifyId();
            Integer newDegree = newQuestionEntity.getDegreeInitial();
            String newKey = courseId + "_" + newQuestionTypeId + "_" + newChapter + "_" + newDegree;
            HashMap<String, List<QuestionMainModel>> mainMap = new HashMap<>(examQuestionMainModelList.size() * 2);

            for (QuestionMainModel examQuestionMainModel : examQuestionMainModelList) {
                //加判空处理 --任蒙蒙
                if (examQuestionMainModel == null) {
                    log.error("从redis取的该科的题examQuestionMainModel is null,课程id为courseId-{},operator-{}", courseId, operator);
                    continue;
                } else {
                    String questionTypeId = examQuestionMainModel.getQuestionTypeId();
                    String chapter = examQuestionMainModel.getQuestionClassifyId();
                    Integer degree = examQuestionMainModel.getDegreeInitial();

                    if (questionTypeId == null || chapter == null) {
                        log.warn("questionTypeId is null or chapter is null,题的id为examQuestionMainModel.getQuestionId()-{}", examQuestionMainModel.getQuestionId());
                        continue;
                    }

                    //获得所有题，形成以courseId +questionTypeId+chapter+degreeInitial为key的map
                    String key = courseId + "_" + questionTypeId + "_" + chapter + "_" + degree;
                    List<QuestionMainModel> examQuestionMainModels = mainMap.get(key);
                    if (examQuestionMainModels == null) {
                        examQuestionMainModels = new ArrayList<>();
                    }
                    examQuestionMainModels.add(examQuestionMainModel);
                    mainMap.put(key, examQuestionMainModels);
                }
            }

            List<QuestionMainModel> queryQuestionList = mainMap.get(newKey);
            for (QuestionMainModel questionMainModel : queryQuestionList) {
                if (questionMainModel.getQuestionId().equals(oldQuestionId)) {
                    //替换旧题
                    examQuestionMainModelList.set(examQuestionMainModelList.indexOf(questionMainModel), newQuestionModel);
                }
            }
            redisTemplate.opsForValue().set(courseKey, examQuestionMainModelList, 3600 * 4, TimeUnit.SECONDS);

        }
        //endregion

//        如果修改的错题是模板必抽题,将新题更新到模板必抽题表
        boolean temflag;
        temflag = templateDetailsExtractService.updateQuestionId(oldQuestionId, newQuestionId);
        if (temflag == true) {
            log.info("修改的错题是模板必抽题,将新题更新到模板必抽题表成功");
        } else {
            log.warn("修改的错题不是模板必抽题或是模板必抽题,将新题更新到模板必抽题表失败");
        }

        //1、查询当前是否有考试，无考试返回null
        List<String> examStudentInfo = examinationService.selectCurrentExam();

        if (examStudentInfo == null || examStudentInfo.size() == 0) {
            log.warn("当前没有有考试,不用通知考生试题修改");
            return false;
        }

        //查当前考试是否有抽到错题的考生
        List<ExamineeModel> examineeList = paperRecordService.selectExamineeByQuestionId(oldQuestionId);

        if (examineeList == null || examineeList.size() == 0) {
            log.warn("当前没有抽到该错题的考生或没有查到抽到该错题的考生,错题id为oldQuestionId-{}", oldQuestionId);
            return false;
        }

        String newQuestionContent = newQuestionEntity.getQuestionContent();
        boolean flagInsert = insertExamineeListForWrongQuestion(examineeList, oldQuestionId, oldQuesitonContent, newQuestionId, newQuestionContent);

        if (flagInsert == false) {
            log.warn("当前考试抽到错题的考生插入changeQuestion表失败");
        }
        boolean flag = updateWrongQuesForExaminee(examineeList, oldQuestionId, newQuestionId);
        if (flag == true) {
            return true;
        } else {
            return false;
        }

    }

    @Transactional(rollbackOn = Exception.class)
    @Override
    public int examOnlineExamineeState() {
        List<ExamineeEntity> examineeEntityList = new ArrayList<>();
        //找出考试时间结束但是考生状态为1的学生
        examineeEntityList = examineeService.examOnlineExamineeState();
        if (examineeEntityList != null && examineeEntityList.size() > 0) {
            //更新考生状态为3,表示考试结束

            int flag = 0;
            try {
                flag = examineeService.updateExamineeStatus(examineeEntityList);
            } catch (Exception e) {
                log.error("xxl-job当考试时间结束,执行更新考生状态为3,(批量更新),考生id-{}", examineeEntityList);
                return -1;
            }
            return flag;
        }
        return 0;
    }

    /**
     * 将抽到错题的考生插入到changeQuestion表
     *
     * @param examineeList       考生列表
     * @param oldQuestionId      旧题干Id
     * @param oldQuesitonContent 旧题干内容
     * @param newQuestionId      新题干Id
     * @param newQuestionContent 新题干内容
     * @return 布尔值
     * @author 任蒙蒙
     */
    @Transactional(rollbackOn = Exception.class)
    public boolean insertExamineeListForWrongQuestion(List<ExamineeModel> examineeList, String oldQuestionId, String oldQuesitonContent, String newQuestionId, String newQuestionContent) {

        boolean flag = false;
        ChangeQuestionModel changeQuestionModel = new ChangeQuestionModel();
        for (ExamineeModel examineeModel : examineeList) {
            String examineeId = examineeModel.getId();
            String examinationId = examineeModel.getExaminationId();
            String examRoomId = examineeModel.getExamRoomId();
            String examName = examineeModel.getExamName();
            String studentId = examineeModel.getStudentId();
            String studentName = examineeModel.getStudentName();
            String studentCode = examineeModel.getStudentCode();
            String examRoomName = examineeModel.getExamRoomName();
            String templateId = examineeModel.getTemplateId();
            String questionTypeId = examineeModel.getQuestionTypeId();
            if (examineeId == null || templateId == null) {
                log.error("examineeId is null or templateId is null,examineeModel-{}", examineeModel);
                continue;
            }
            changeQuestionModel.setExamineeId(examineeId);
            changeQuestionModel.setExaminationId(examinationId);
            changeQuestionModel.setExamRoomId(examRoomId);
            changeQuestionModel.setExamName(examName);
            changeQuestionModel.setStudentId(studentId);
            changeQuestionModel.setStudentName(studentName);
            changeQuestionModel.setStudentCode(studentCode);
            changeQuestionModel.setExamRoomName(examRoomName);
            changeQuestionModel.setOldQuestionContent(oldQuesitonContent);
            changeQuestionModel.setOldQuestionId(oldQuestionId);
            changeQuestionModel.setNewQuestionId(newQuestionId);
            changeQuestionModel.setNewQuestionContent(newQuestionContent);
            changeQuestionModel.setTemplateId(templateId);
            changeQuestionModel.setQuestionTypeId(questionTypeId);

            boolean everyflag = changeQuestionService.insertExamineeForWrongQuestion(changeQuestionModel);
            if (everyflag == true) {
                flag = true;
            } else {
                flag = false;
            }
        }
        return flag;
    }

    @Override
    public ExamPaperModel queryQuestionForFix(String courseId, String templateId, String operator) {
        //抽题
        ExamPaperModel examPaperModel = getPaperByTemplateRandom(templateId, "考生id-固定抽题模板使用", courseId, operator);
        if (ObjectUtils.isEmpty(examPaperModel)) {
            log.error("getPaperByTemplate查询为空,执行失败!templeatId-{},examineeId-{},courseId-{},operator-{}", templateId, "6666", courseId, operator);
            return null;
        }

        //业务题处理操作需要去掉答案
        examPaperModel = dealBusinessProblems(examPaperModel);
        //排序
        getPaperSort(examPaperModel);
        //将抽出的题放入redis
        String templateExamineeCourseId = "practice" + "templateId=" + templateId + "courseId=" + courseId + "operator=" + operator;

        redisTemplate.opsForValue().set(templateExamineeCourseId, examPaperModel);
        redisTemplate.expire(templateExamineeCourseId, 3600 * 4, TimeUnit.SECONDS);

        return examPaperModel;
    }

    /**
     * 一级考试接口
     *
     * @param studentCode 学号
     * @param score       操作题总分
     * @return 剩余分钟数
     * @author 王雪芬
     * @since 2019年2月16日
     */
    @Override
    public boolean getExamOneLevel(String studentCode, Double score) {
        PaperRecordEntity paperRecordEntity = (PaperRecordEntity) redisTemplate.opsForValue().get(studentCode);
        if (paperRecordEntity == null) {
            log.warn("一级考试更新操作题总分失败,studentCode-{},score-{}", studentCode, score);
            return false;
        }
        PaperOnlineRecordModel paperOnlineRecordModel = new PaperOnlineRecordModel();
        paperOnlineRecordModel.setPaperRecordId(paperRecordEntity.getId());
        paperOnlineRecordModel.setExaminationId(paperRecordEntity.getExaminationId());
        paperOnlineRecordModel.setExamineeId(paperRecordEntity.getExamineeId());
        paperOnlineRecordModel.setQuestionTypeId(paperRecordEntity.getQuestionTypeId());
        paperOnlineRecordModel.setScore(score);
        paperOnlineRecordModel.setTypeName("操作题");
        paperOnlineRecordModel.setQuestionTypeId(paperRecordEntity.getQuestionTypeId());
        paperOnlineRecordModel.setQuestionCode("21");
        paperOnlineRecordModel.setTemplateId(paperRecordEntity.getTemplateId());
        paperOnlineRecordModel.setQuestionMainId(paperRecordEntity.getQuestionId());
        boolean record = updateExamPaperRecord(paperOnlineRecordModel);

        //考生交卷
        if (record == true) {
            ExamineeEntity examineeEntity = examineeService.getById(paperRecordEntity.getExamineeId());
            if (examineeEntity == null) {
                log.info("一级考生交卷失败,examineeEntity is null ,paperRecordEntity-{}", paperRecordEntity);
                return false;
            }
            boolean updateExamStateBySumit = updateExamStateBySumit(examineeEntity);
            return updateExamStateBySumit;
        }
        log.info("一级考生操作题成绩更新失败 ,paperOnlineRecordModel-{}", paperOnlineRecordModel);
        return false;
    }

    @Override
    public long queryExamTimeOneLevel(String studentCode) {

        List<StudentModel> studentModels = studentService.findByCode(studentCode);
        if (CollectionUtils.isEmpty(studentModels)) {
            log.info("一级接口查询剩余考试时间,studentCode is exsit ,studentCode-{}", studentCode);
            return 0;
        }
        ExaminOnlineModel examinOnlineModel = queryExamStudentInfoLogin(studentModels.get(0).getId());
        if (examinOnlineModel == null) {
            log.info("一级接口查询剩余考试时间,examinOnlineModel is null 获取考试信息 ,studentCode-{}", studentCode);
            return 0;
        }
        if (examinOnlineModel.getExameeid() != null) {
            ExamineeEntity examineeEntity = examineeService.getById(examinOnlineModel.getExameeid());
            if (examineeEntity != null && examineeEntity.getShouldSubmitTime() != null) {
                examinOnlineModel.setShouldSubmitTime(examineeEntity.getShouldSubmitTime());
            }
        }
        if (examinOnlineModel.getShouldSubmitTime() != null && examinOnlineModel.getExamDuration() != null) {
            long time = examinOnlineModel.getShouldSubmitTime().getTime();
            long examDuration = examinOnlineModel.getExamDuration();
            Date now = new Date();
            long nowTime = now.getTime();
            //理论时间大于当前时间
            if (nowTime <= time) {
                long remainTime = time - nowTime;
                remainTime = remainTime / 60000;
                //总时长大于剩余时长
                return remainTime;
            }
            log.info("一级接口查询剩余考试时间,剩余时间大于小于总时长,studentCode-{},remainTime-{},examDuration-{}", studentCode, examDuration);
            return 0;
        }
        log.info("一级接口查询剩余考试时间,理论结束时间不能小于当前时间,studentCode-{}, time-{},nowTime-{}", studentCode);
        return 0;
    }


//
//    @Override
//      public   boolean updateExamPaperRecordIsRabbit(PaperOnlineRecordModel paperOnlineRecordModel){
//        boolean flag = false;
//        if(getRabbitmq.equals(1)){
//            Message msg = MessageBuilder
//                    .withBody(Objects.requireNonNull(SerializationUtils.serialize(paperOnlineRecordModel)))
//                    .build();
//            rabbitTemplate.convertAndSend(msg);
//            ObjectMapper mapper = new ObjectMapper();
//            String json = new String();
//            return true;
//        }else{
//            flag= updateExamPaperRecord(paperOnlineRecordModel);
//        }
//        return flag;
//    }


    @Override
    public boolean downLoadStudentOneLevel(String studentCode) {
        //文件+名称
        String path = "D:\\";
        //创建文件
        boolean file = createFile(path, studentCode);
        if (file) {
            //向文件中写入内容
            boolean contentBollean = wirteFileContent(path, studentCode);
            return contentBollean;
        }
        //删除文件
        return false;
    }

    @Override
    public boolean updateExamPaperRecordIsRabbit(PaperOnlineRecordModel paperOnlineRecordModel) {
        return false;
    }

    /**
     * 创建文件
     *
     * @param fileName   文件
     * @param fileConent 文件内容
     * @return
     */
    public boolean createFile(String fileName, String fileConent) {
        String filenameTemp = fileName + fileConent + ".txt";//文件路径+名称+文件类型;
        File file = new File(filenameTemp);
        try {
            //判断文件是否存在
            if (!file.exists()) {
                //创建文件
                boolean newFile = file.createNewFile();
                if (newFile) {
                    boolean wirteFileContent = wirteFileContent(filenameTemp, fileConent);
                    return wirteFileContent;
                }
            }
            log.warn("一级创建文件,已存在无法删除,请删除C盘文件");
            return false;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 文件写内容
     *
     * @param filePath 文件路径
     * @param newStr   内容
     * @return
     */
    public boolean wirteFileContent(String filePath, String newStr) {
        String fileIn = newStr + "\r\n";
        String temp = "";
        File file = new File(filePath);
        FileInputStream fis = null;
        InputStreamReader isr = null;
        BufferedReader br = null;
        FileOutputStream fos = null;
        PrintWriter pw = null;
        try {
            //将文件读入输入流
            fis = new FileInputStream(file);
            isr = new InputStreamReader(fis);
            br = new BufferedReader(isr);
            StringBuffer buffer = new StringBuffer();
            for (int i = 0; (temp = br.readLine()) != null; i++) {
                buffer.append(temp);
                buffer = buffer.append(System.getProperty("line.separator"));
            }
            buffer.append(fileIn);
            fos = new FileOutputStream(file);
            pw = new PrintWriter(fos);
            pw.write(buffer.toString().toCharArray());
            pw.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                //不要忘记关闭
                if (pw != null) {
                    pw.close();
                }
                if (fos != null) {
                    fos.close();
                }
                if (br != null) {
                    br.close();
                }
                if (isr != null) {
                    isr.close();
                }
                if (fis != null) {
                    fis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return true;
    }

    /**
     * 删除文件
     *
     * @param fileName 文件名
     * @return
     */
    public boolean delFile(String fileName) {
        return false;
    }


    /**
     * 课程练习-保存学生答题记录
     *
     * @param examPaperModel
     * @return 是否插入成功
     * @author 贾建清
     * @since 2.0.0 2019-3-26 15:48:15
     */
    @Override
    public List<PaperRecordEntity> insertPaperRecord(CoursePaperRecordModel coursePaperRecordModel) {
        List<PaperRecordEntity> paperRecordEntityList = paperRecordDao.insertPaperRecord(coursePaperRecordModel);
        return paperRecordEntityList;
    }

}

